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 Synchronization Tests
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fSynchronizationTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSharedPtr.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool validateSortedAtomicRampAdditionValueChain (const std::vector<deUint32>& valueChain, deUint32 sumValue, int& invalidOperationNdx, deUint32& errorDelta, deUint32& errorExpected)
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32> chainDelta(valueChain.size());
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int callNdx = 0; callNdx < (int)valueChain.size(); ++callNdx)
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		chainDelta[callNdx] = ((callNdx + 1 == (int)valueChain.size()) ? (sumValue) : (valueChain[callNdx+1])) - valueChain[callNdx];
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// chainDelta contains now the actual additions applied to the value
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// check there exists an addition ramp form 1 to ...
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::sort(chainDelta.begin(), chainDelta.end());
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int callNdx = 0; callNdx < (int)valueChain.size(); ++callNdx)
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((int)chainDelta[callNdx] != callNdx+1)
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			invalidOperationNdx = callNdx;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			errorDelta = chainDelta[callNdx];
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			errorExpected = callNdx+1;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void readBuffer (const glw::Functions& gl, deUint32 target, int numElements, std::vector<deUint32>& result)
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const void* ptr = gl.mapBufferRange(target, 0, (int)(sizeof(deUint32) * numElements), GL_MAP_READ_BIT);
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "map");
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!ptr)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("mapBufferRange returned NULL");
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	result.resize(numElements);
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	memcpy(&result[0], ptr, sizeof(deUint32) * numElements);
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (gl.unmapBuffer(target) == GL_FALSE)
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("unmapBuffer returned false");
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 readBufferUint32 (const glw::Functions& gl, deUint32 target)
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32> vec;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	readBuffer(gl, target, 1, vec);
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return vec[0];
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Generate a ramp of values from 1 to numElements, and shuffle it
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid generateShuffledRamp (int numElements, std::vector<int>& ramp)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rng(0xabcd);
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// some positive (non-zero) unique values
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ramp.resize(numElements);
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int callNdx = 0; callNdx < numElements; ++callNdx)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ramp[callNdx] = callNdx + 1;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	rng.shuffle(ramp.begin(), ramp.end());
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InterInvocationTestCase : public TestCase
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum StorageType
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STORAGE_BUFFER = 0,
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STORAGE_IMAGE,
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STORAGE_LAST
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseFlags
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_ATOMIC				= 0x1,
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_ALIASING_STORAGES	= 0x2,
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_IN_GROUP			= 0x4,
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						InterInvocationTestCase		(Context& context, const char* name, const char* desc, StorageType storage, int flags = 0);
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~InterInvocationTestCase	(void);
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init						(void);
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				deinit						(void);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult		iterate						(void);
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				runCompute					(void);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				verifyResults				(void);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual std::string	genShaderSource				(void) const = 0;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			genBarrierSource			(void) const;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const StorageType	m_storage;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			m_useAtomic;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			m_aliasingStorages;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			m_syncWithGroup;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_workWidth;				// !< total work width
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_workHeight;				// !<     ...    height
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_localWidth;				// !< group width
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_localHeight;				// !< group height
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_elementsPerInvocation;	// !< elements accessed by a single invocation
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint			m_storageBuf;
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint			m_storageTex;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint			m_resultBuf;
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*	m_program;
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1643c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterInvocationTestCase::InterInvocationTestCase (Context& context, const char* name, const char* desc, StorageType storage, int flags)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, desc)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_storage					(storage)
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_useAtomic				((flags & FLAG_ATOMIC) != 0)
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_aliasingStorages		((flags & FLAG_ALIASING_STORAGES) != 0)
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_syncWithGroup			((flags & FLAG_IN_GROUP) != 0)
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workWidth				(256)
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workHeight				(256)
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_localWidth				(16)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_localHeight				(8)
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_elementsPerInvocation	(8)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_storageBuf				(0)
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_storageTex				(0)
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_resultBuf				(0)
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program					(DE_NULL)
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_storage < STORAGE_LAST);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_localWidth*m_localHeight <= 128); // minimum MAX_COMPUTE_WORK_GROUP_INVOCATIONS value
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterInvocationTestCase::~InterInvocationTestCase (void)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterInvocationTestCase::init (void)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// requirements
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_useAtomic && m_storage == STORAGE_IMAGE && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic"))
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_OES_shader_image_atomic extension");
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// program
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genShaderSource()));
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("could not build program");
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// source
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bufferElements	= m_workWidth * m_workHeight * m_elementsPerInvocation;
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bufferSize		= bufferElements * sizeof(deUint32);
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32>	zeroBuffer		(bufferElements, 0);
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Allocating zero-filled buffer for storage, size " << bufferElements << " elements, " << bufferSize << " bytes." << tcu::TestLog::EndMessage;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_storageBuf);
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_storageBuf);
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &zeroBuffer[0], GL_STATIC_DRAW);
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen storage buf");
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bufferElements	= m_workWidth * m_workHeight * m_elementsPerInvocation;
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bufferSize		= bufferElements * sizeof(deUint32);
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Allocating image for storage, size " << m_workWidth << "x" << m_workHeight * m_elementsPerInvocation << ", " << bufferSize << " bytes." << tcu::TestLog::EndMessage;
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genTextures(1, &m_storageTex);
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindTexture(GL_TEXTURE_2D, m_storageTex);
2298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_workWidth, m_workHeight * m_elementsPerInvocation);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen storage image");
2338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// Zero-fill
2358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Filling image with 0." << tcu::TestLog::EndMessage;
2368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
2378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
2388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const std::vector<deInt32> zeroBuffer(m_workWidth * m_workHeight * m_elementsPerInvocation, 0);
2398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_workWidth, m_workHeight * m_elementsPerInvocation, GL_RED_INTEGER, GL_INT, &zeroBuffer[0]);
2408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "specify image contents");
2418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// destination
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bufferElements	= m_workWidth * m_workHeight;
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				bufferSize		= bufferElements * sizeof(deUint32);
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deInt32>	negativeBuffer	(bufferElements, -1);
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Allocating -1 filled buffer for results, size " << bufferElements << " elements, " << bufferSize << " bytes." << tcu::TestLog::EndMessage;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_resultBuf);
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_resultBuf);
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &negativeBuffer[0], GL_STATIC_DRAW);
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen storage buf");
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterInvocationTestCase::deinit (void)
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storageBuf)
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_storageBuf);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_storageBuf = DE_NULL;
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storageTex)
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_storageTex);
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_storageTex = DE_NULL;
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_resultBuf)
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_resultBuf);
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_resultBuf = DE_NULL;
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterInvocationTestCase::IterateResult InterInvocationTestCase::iterate (void)
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Dispatch
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	runCompute();
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify buffer contents
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (verifyResults())
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, (std::string((m_storage == STORAGE_BUFFER) ? ("buffer") : ("image")) + " content verification failed").c_str());
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterInvocationTestCase::runCompute (void)
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				groupsX	= m_workWidth / m_localWidth;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				groupsY	= m_workHeight / m_localHeight;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((m_workWidth % m_localWidth) == 0);
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((m_workHeight % m_localHeight) == 0);
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Dispatching compute.\n"
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	group size: " << m_localWidth << "x" << m_localHeight << "\n"
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	dispatch size: " << groupsX << "x" << groupsY << "\n"
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	total work size: " << m_workWidth << "x" << m_workHeight << "\n"
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_program->getProgram());
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// source
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER && !m_aliasingStorages)
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storageBuf);
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind source buf");
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_BUFFER && m_aliasingStorages)
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storageBuf);
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storageBuf);
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind source buf");
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Binding same buffer object to buffer storages." << tcu::TestLog::EndMessage;
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE && !m_aliasingStorages)
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(1, m_storageTex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind result buf");
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE && m_aliasingStorages)
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(1, m_storageTex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(2, m_storageTex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind result buf");
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Binding same texture level to image storages." << tcu::TestLog::EndMessage;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// destination
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_resultBuf);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind result buf");
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// dispatch
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.dispatchCompute(groupsX, groupsY, 1);
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "dispatchCompute");
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool InterInvocationTestCase::verifyResults (void)
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				errorFloodThreshold	= 5;
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						numErrorsLogged		= 0;
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const void*				mapped				= DE_NULL;
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deInt32>	results				(m_workWidth * m_workHeight);
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					error				= false;
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_resultBuf);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mapped = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_workWidth * m_workHeight * sizeof(deInt32), GL_MAP_READ_BIT);
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "map buffer");
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// copy to properly aligned array
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemcpy(&results[0], mapped, m_workWidth * m_workHeight * sizeof(deUint32));
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER) != GL_TRUE)
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("memory map store corrupted");
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// check the results
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)results.size(); ++ndx)
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (results[ndx] != 1)
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			error = true;
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numErrorsLogged == 0)
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Result buffer failed, got unexpected values.\n" << tcu::TestLog::EndMessage;
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numErrorsLogged++ < errorFloodThreshold)
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "	Error at index " << ndx << ": expected 1, got " << results[ndx] << ".\n" << tcu::TestLog::EndMessage;
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// after N errors, no point continuing verification
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "	-- too many errors, skipping verification --\n" << tcu::TestLog::EndMessage;
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!error)
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Result buffer ok." << tcu::TestLog::EndMessage;
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return !error;
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string InterInvocationTestCase::genBarrierSource (void) const
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_syncWithGroup)
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Wait until all invocations in this work group have their texture/buffer read/write operations complete
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note We could also use memoryBarrierBuffer() or memoryBarrierImage() in place of groupMemoryBarrier() but
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		//       we only require intra-workgroup synchronization.
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\n"
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	groupMemoryBarrier();\n"
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	barrier();\n"
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\n";
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_BUFFER)
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!m_syncWithGroup);
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Waiting only for data written by this invocation. Since all buffer reads and writes are
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// processed in order (within a single invocation), we don't have to do anything.
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\n";
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!m_syncWithGroup);
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Waiting only for data written by this invocation. But since operations complete in undefined
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// order, we have to wait for them to complete.
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\n"
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	memoryBarrierImage();\n"
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\n";
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvocationBasicCase : public InterInvocationTestCase
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							InvocationBasicCase		(Context& context, const char* name, const char* desc, StorageType storage, int flags);
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genShaderSource			(void) const;
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual std::string		genShaderMainBlock		(void) const = 0;
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvocationBasicCase::InvocationBasicCase (Context& context, const char* name, const char* desc, StorageType storage, int flags)
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InterInvocationTestCase(context, name, desc, storage, flags)
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string InvocationBasicCase::genShaderSource (void) const
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x=" << m_localWidth << ", local_size_y=" << m_localHeight << ") in;\n"
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout(binding=0, std430) buffer Output\n"
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp int values[];\n"
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_result;\n";
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=1, std430) coherent buffer Storage\n"
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp int values[];\n"
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_store;\n"
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\n"
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "highp int getIndex (in highp uvec2 localID, in highp int element)\n"
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp uint groupNdx = gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	return int((localID.y * gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupSize.x) + (groupNdx * gl_WorkGroupSize.x) + localID.x) * " << m_elementsPerInvocation << " + element;\n"
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "}\n";
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(r32i, binding=1) coherent uniform highp iimage2D u_image;\n"
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\n"
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "highp ivec2 getCoord (in highp uvec2 localID, in highp int element)\n"
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	return ivec2(int(gl_WorkGroupID.x * gl_WorkGroupSize.x + localID.x), int(gl_WorkGroupID.y * gl_WorkGroupSize.y + localID.y) + element * " << m_workHeight << ");\n"
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "}\n";
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "\n"
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int resultNdx   = int(gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x + gl_GlobalInvocationID.x);\n"
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx    = int(gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x);\n"
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	bool allOk      = true;\n"
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< genShaderMainBlock()
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	sb_result.values[resultNdx] = (allOk) ? (1) : (0);\n"
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvocationWriteReadCase : public InvocationBasicCase
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					InvocationWriteReadCase		(Context& context, const char* name, const char* desc, StorageType storage, int flags);
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		genShaderMainBlock			(void) const;
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvocationWriteReadCase::InvocationWriteReadCase (Context& context, const char* name, const char* desc, StorageType storage, int flags)
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InvocationBasicCase(context, name, desc, storage, flags)
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string InvocationWriteReadCase::genShaderMainBlock (void) const
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// write
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tatomicAdd(sb_store.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")], groupNdx);\n";
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tsb_store.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")] = groupNdx;\n";
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageAtomicAdd(u_image, getCoord(gl_LocalInvocationID.xy, " << ndx << "), int(groupNdx));\n";
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageStore(u_image, getCoord(gl_LocalInvocationID.xy, " << ndx << "), ivec4(int(groupNdx), 0, 0, 0));\n";
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// barrier
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << genBarrierSource();
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// read
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string localID = (m_syncWithGroup) ? ("(gl_LocalInvocationID.xy + uvec2(" + de::toString(ndx+1) + ", " + de::toString(2*ndx) + ")) % gl_WorkGroupSize.xy") : ("gl_LocalInvocationID.xy");
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (atomicExchange(sb_store.values[getIndex(" << localID << ", " << ndx << ")], 0) == groupNdx);\n";
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (sb_store.values[getIndex(" << localID << ", " << ndx << ")] == groupNdx);\n";
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageAtomicExchange(u_image, getCoord(" << localID << ", " << ndx << "), 0) == groupNdx);\n";
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageLoad(u_image, getCoord(" << localID << ", " << ndx << ")).x == groupNdx);\n";
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvocationReadWriteCase : public InvocationBasicCase
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					InvocationReadWriteCase		(Context& context, const char* name, const char* desc, StorageType storage, int flags);
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		genShaderMainBlock			(void) const;
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvocationReadWriteCase::InvocationReadWriteCase (Context& context, const char* name, const char* desc, StorageType storage, int flags)
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InvocationBasicCase(context, name, desc, storage, flags)
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string InvocationReadWriteCase::genShaderMainBlock (void) const
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// read
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string localID = (m_syncWithGroup) ? ("(gl_LocalInvocationID.xy + uvec2(" + de::toString(ndx+1) + ", " + de::toString(2*ndx) + ")) % gl_WorkGroupSize.xy") : ("gl_LocalInvocationID.xy");
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (atomicExchange(sb_store.values[getIndex(" << localID << ", " << ndx << ")], 123) == 0);\n";
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (sb_store.values[getIndex(" << localID << ", " << ndx << ")] == 0);\n";
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageAtomicExchange(u_image, getCoord(" << localID << ", " << ndx << "), 123) == 0);\n";
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageLoad(u_image, getCoord(" << localID << ", " << ndx << ")).x == 0);\n";
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// barrier
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << genBarrierSource();
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// write
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tatomicAdd(sb_store.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")], groupNdx);\n";
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tsb_store.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")] = groupNdx;\n";
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageAtomicAdd(u_image, getCoord(gl_LocalInvocationID.xy, " << ndx << "), int(groupNdx));\n";
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageStore(u_image, getCoord(gl_LocalInvocationID.xy, " << ndx << "), ivec4(int(groupNdx), 0, 0, 0));\n";
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvocationOverWriteCase : public InvocationBasicCase
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					InvocationOverWriteCase		(Context& context, const char* name, const char* desc, StorageType storage, int flags);
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		genShaderMainBlock			(void) const;
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6283c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvocationOverWriteCase::InvocationOverWriteCase (Context& context, const char* name, const char* desc, StorageType storage, int flags)
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InvocationBasicCase(context, name, desc, storage, flags)
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string InvocationOverWriteCase::genShaderMainBlock (void) const
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// write
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tatomicAdd(sb_store.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")], 456);\n";
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tsb_store.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")] = 456;\n";
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageAtomicAdd(u_image, getCoord(gl_LocalInvocationID.xy, " << ndx << "), 456);\n";
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageStore(u_image, getCoord(gl_LocalInvocationID.xy, " << ndx << "), ivec4(456, 0, 0, 0));\n";
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// barrier
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << genBarrierSource();
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// write over
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// write another invocation's value or our own value depending on test type
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string localID = (m_syncWithGroup) ? ("(gl_LocalInvocationID.xy + uvec2(" + de::toString(ndx+4) + ", " + de::toString(3*ndx) + ")) % gl_WorkGroupSize.xy") : ("gl_LocalInvocationID.xy");
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tatomicExchange(sb_store.values[getIndex(" << localID << ", " << ndx << ")], groupNdx);\n";
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tsb_store.values[getIndex(" << localID << ", " << ndx << ")] = groupNdx;\n";
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageAtomicExchange(u_image, getCoord(" << localID << ", " << ndx << "), groupNdx);\n";
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageStore(u_image, getCoord(" << localID << ", " << ndx << "), ivec4(groupNdx, 0, 0, 0));\n";
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// barrier
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << genBarrierSource();
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// read
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// check another invocation's value or our own value depending on test type
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string localID = (m_syncWithGroup) ? ("(gl_LocalInvocationID.xy + uvec2(" + de::toString(ndx+1) + ", " + de::toString(2*ndx) + ")) % gl_WorkGroupSize.xy") : ("gl_LocalInvocationID.xy");
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (atomicExchange(sb_store.values[getIndex(" << localID << ", " << ndx << ")], 123) == groupNdx);\n";
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (sb_store.values[getIndex(" << localID << ", " << ndx << ")] == groupNdx);\n";
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageAtomicExchange(u_image, getCoord(" << localID << ", " << ndx << "), 123) == groupNdx);\n";
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageLoad(u_image, getCoord(" << localID << ", " << ndx << ")).x == groupNdx);\n";
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InvocationAliasWriteCase : public InterInvocationTestCase
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum TestType
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TYPE_WRITE = 0,
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TYPE_OVERWRITE,
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TYPE_LAST
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					InvocationAliasWriteCase	(Context& context, const char* name, const char* desc, TestType type, StorageType storage, int flags);
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		genShaderSource				(void) const;
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TestType	m_type;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInvocationAliasWriteCase::InvocationAliasWriteCase (Context& context, const char* name, const char* desc, TestType type, StorageType storage, int flags)
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: InterInvocationTestCase	(context, name, desc, storage, flags | FLAG_ALIASING_STORAGES)
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_type					(type)
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(type < TYPE_LAST);
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string InvocationAliasWriteCase::genShaderSource (void) const
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x=" << m_localWidth << ", local_size_y=" << m_localHeight << ") in;\n"
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout(binding=0, std430) buffer Output\n"
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp int values[];\n"
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_result;\n";
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=1, std430) coherent buffer Storage0\n"
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp int values[];\n"
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_store0;\n"
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "layout(binding=2, std430) coherent buffer Storage1\n"
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp int values[];\n"
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_store1;\n"
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\n"
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "highp int getIndex (in highp uvec2 localID, in highp int element)\n"
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp uint groupNdx = gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	return int((localID.y * gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupSize.x) + (groupNdx * gl_WorkGroupSize.x) + localID.x) * " << m_elementsPerInvocation << " + element;\n"
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "}\n";
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(r32i, binding=1) coherent uniform highp iimage2D u_image0;\n"
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "layout(r32i, binding=2) coherent uniform highp iimage2D u_image1;\n"
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "\n"
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "highp ivec2 getCoord (in highp uvec2 localID, in highp int element)\n"
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	return ivec2(int(gl_WorkGroupID.x * gl_WorkGroupSize.x + localID.x), int(gl_WorkGroupID.y * gl_WorkGroupSize.y + localID.y) + element * " << m_workHeight << ");\n"
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "}\n";
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "\n"
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int resultNdx   = int(gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x + gl_GlobalInvocationID.x);\n"
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx    = int(gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x);\n"
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	bool allOk      = true;\n"
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_type == TYPE_OVERWRITE)
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// write
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_storage == STORAGE_BUFFER && m_useAtomic)
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "\tatomicAdd(sb_store0.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")], 456);\n";
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "\tsb_store0.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")] = 456;\n";
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_storage == STORAGE_IMAGE && m_useAtomic)
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "\timageAtomicAdd(u_image0, getCoord(gl_LocalInvocationID.xy, " << ndx << "), 456);\n";
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "\timageStore(u_image0, getCoord(gl_LocalInvocationID.xy, " << ndx << "), ivec4(456, 0, 0, 0));\n";
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(DE_FALSE);
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// barrier
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << genBarrierSource();
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_type == TYPE_WRITE);
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// write (again)
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::string localID = (m_syncWithGroup) ? ("(gl_LocalInvocationID.xy + uvec2(" + de::toString(ndx+2) + ", " + de::toString(2*ndx) + ")) % gl_WorkGroupSize.xy") : ("gl_LocalInvocationID.xy");
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tatomicExchange(sb_store1.values[getIndex(" << localID << ", " << ndx << ")], groupNdx);\n";
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tsb_store1.values[getIndex(" << localID << ", " << ndx << ")] = groupNdx;\n";
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageAtomicExchange(u_image1, getCoord(" << localID << ", " << ndx << "), groupNdx);\n";
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\timageStore(u_image1, getCoord(" << localID << ", " << ndx << "), ivec4(groupNdx, 0, 0, 0));\n";
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// barrier
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << genBarrierSource();
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// read
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_elementsPerInvocation; ++ndx)
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER && m_useAtomic)
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (atomicExchange(sb_store0.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")], 123) == groupNdx);\n";
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_BUFFER && !m_useAtomic)
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, " << ndx << ")] == groupNdx);\n";
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && m_useAtomic)
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageAtomicExchange(u_image0, getCoord(gl_LocalInvocationID.xy, " << ndx << "), 123) == groupNdx);\n";
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE && !m_useAtomic)
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "\tallOk = allOk && (imageLoad(u_image0, getCoord(gl_LocalInvocationID.xy, " << ndx << ")).x == groupNdx);\n";
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// return result
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "\n"
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	sb_result.values[resultNdx] = (allOk) ? (1) : (0);\n"
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace op
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct WriteData
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int targetHandle;
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int seed;
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static WriteData Generate(int targetHandle, int seed)
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WriteData retVal;
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle = targetHandle;
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed = seed;
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ReadData
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int targetHandle;
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int seed;
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ReadData Generate(int targetHandle, int seed)
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ReadData retVal;
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle = targetHandle;
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed = seed;
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Barrier
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct WriteDataInterleaved
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		targetHandle;
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		seed;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	evenOdd;
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static WriteDataInterleaved Generate(int targetHandle, int seed, bool evenOdd)
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WriteDataInterleaved retVal;
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle = targetHandle;
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed = seed;
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.evenOdd = evenOdd;
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ReadDataInterleaved
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int targetHandle;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int seed0;
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int seed1;
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ReadDataInterleaved Generate(int targetHandle, int seed0, int seed1)
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ReadDataInterleaved retVal;
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle = targetHandle;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed0 = seed0;
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed1 = seed1;
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ReadMultipleData
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int targetHandle0;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int seed0;
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int targetHandle1;
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int seed1;
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ReadMultipleData Generate(int targetHandle0, int seed0, int targetHandle1, int seed1)
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ReadMultipleData retVal;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle0 = targetHandle0;
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed0 = seed0;
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle1 = targetHandle1;
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.seed1 = seed1;
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ReadZeroData
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int targetHandle;
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static ReadZeroData Generate(int targetHandle)
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ReadZeroData retVal;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		retVal.targetHandle = targetHandle;
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // namespace op
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InterCallTestCase;
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InterCallOperations
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::WriteData&);
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::ReadData&);
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::Barrier&);
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::ReadMultipleData&);
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::WriteDataInterleaved&);
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::ReadDataInterleaved&);
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	InterCallOperations& operator<< (const op::ReadZeroData&);
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct Command
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		enum CommandType
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_WRITE = 0,
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_READ,
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_BARRIER,
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_READ_MULTIPLE,
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_WRITE_INTERLEAVE,
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_READ_INTERLEAVE,
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_READ_ZERO,
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_LAST
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CommandType type;
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		union CommandUnion
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::WriteData				write;
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::ReadData				read;
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::Barrier					barrier;
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::ReadMultipleData		readMulti;
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::WriteDataInterleaved	writeInterleave;
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::ReadDataInterleaved		readInterleave;
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			op::ReadZeroData			readZero;
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} u_cmd;
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	friend class InterCallTestCase;
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Command> m_cmds;
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::WriteData& cmd)
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_WRITE;
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.write = cmd;
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10143c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::ReadData& cmd)
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_READ;
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.read = cmd;
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10233c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::Barrier& cmd)
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_BARRIER;
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.barrier = cmd;
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10323c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::ReadMultipleData& cmd)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_READ_MULTIPLE;
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.readMulti = cmd;
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::WriteDataInterleaved& cmd)
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_WRITE_INTERLEAVE;
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.writeInterleave = cmd;
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::ReadDataInterleaved& cmd)
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_READ_INTERLEAVE;
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.readInterleave = cmd;
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallOperations& InterCallOperations::operator<< (const op::ReadZeroData& cmd)
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.push_back(Command());
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().type = Command::TYPE_READ_ZERO;
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_cmds.back().u_cmd.readZero = cmd;
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass InterCallTestCase : public TestCase
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum StorageType
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STORAGE_BUFFER = 0,
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STORAGE_IMAGE,
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		STORAGE_LAST
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum Flags
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_USE_ATOMIC	= 1,
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_USE_INT	= 2,
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													InterCallTestCase			(Context& context, const char* name, const char* desc, StorageType storage, int flags, const InterCallOperations& ops);
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													~InterCallTestCase			(void);
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											init						(void);
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											deinit						(void);
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult									iterate						(void);
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool											verifyResults				(void);
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::WriteData& cmd, int stepNdx, int& programFriendlyName);
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::ReadData& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName);
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::Barrier&);
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::ReadMultipleData& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName);
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::WriteDataInterleaved& cmd, int stepNdx, int& programFriendlyName);
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::ReadDataInterleaved& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName);
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runCommand					(const op::ReadZeroData& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName);
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void											runSingleRead				(int targetHandle, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName);
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint										genStorage					(int friendlyName);
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint										genResultStorage			(void);
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*								genWriteProgram				(int seed);
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*								genReadProgram				(int seed);
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*								genReadMultipleProgram		(int seed0, int seed1);
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*								genWriteInterleavedProgram	(int seed, bool evenOdd);
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*								genReadInterleavedProgram	(int seed0, int seed1);
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*								genReadZeroProgram			(void);
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const StorageType								m_storage;
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										m_invocationGridSize;	// !< width and height of the two dimensional work dispatch
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int										m_perInvocationSize;	// !< number of elements accessed in single invocation
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<InterCallOperations::Command>	m_cmds;
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool										m_useAtomic;
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool										m_formatInteger;
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<glu::ShaderProgram*>				m_operationPrograms;
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<glw::GLuint>						m_operationResultStorages;
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::map<int, glw::GLuint>						m_storageIDs;
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallTestCase::InterCallTestCase (Context& context, const char* name, const char* desc, StorageType storage, int flags, const InterCallOperations& ops)
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, desc)
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_storage					(storage)
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_invocationGridSize		(512)
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_perInvocationSize		(2)
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_cmds					(ops.m_cmds)
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_useAtomic				((flags & FLAG_USE_ATOMIC) != 0)
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_formatInteger			((flags & FLAG_USE_INT) != 0)
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallTestCase::~InterCallTestCase (void)
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::init (void)
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int programFriendlyName = 0;
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// requirements
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_useAtomic && m_storage == STORAGE_IMAGE && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic"))
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_OES_shader_image_atomic extension");
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// generate resources and validate command list
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_operationPrograms.resize(m_cmds.size(), DE_NULL);
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_operationResultStorages.resize(m_cmds.size(), 0);
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int step = 0; step < (int)m_cmds.size(); ++step)
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_cmds[step].type)
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_WRITE:
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const op::WriteData& cmd = m_cmds[step].u_cmd.write;
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// new storage handle?
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_storageIDs.find(cmd.targetHandle) == m_storageIDs.end())
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_storageIDs[cmd.targetHandle] = genStorage(cmd.targetHandle);
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::ShaderProgram* program = genWriteProgram(cmd.seed);
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Program #" << ++programFriendlyName << tcu::TestLog::EndMessage;
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *program;
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!program->isOk())
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw tcu::TestError("could not build program");
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationPrograms[step] = program;
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ:
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const op::ReadData& cmd = m_cmds[step].u_cmd.read;
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_storageIDs.find(cmd.targetHandle) != m_storageIDs.end());
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program and result storage
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::ShaderProgram* program = genReadProgram(cmd.seed);
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Program #" << ++programFriendlyName << tcu::TestLog::EndMessage;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *program;
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!program->isOk())
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw tcu::TestError("could not build program");
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationPrograms[step] = program;
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationResultStorages[step] = genResultStorage();
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_BARRIER:
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ_MULTIPLE:
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const op::ReadMultipleData& cmd = m_cmds[step].u_cmd.readMulti;
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_storageIDs.find(cmd.targetHandle0) != m_storageIDs.end());
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_storageIDs.find(cmd.targetHandle1) != m_storageIDs.end());
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::ShaderProgram* program = genReadMultipleProgram(cmd.seed0, cmd.seed1);
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Program #" << ++programFriendlyName << tcu::TestLog::EndMessage;
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *program;
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!program->isOk())
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw tcu::TestError("could not build program");
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationPrograms[step] = program;
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationResultStorages[step] = genResultStorage();
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_WRITE_INTERLEAVE:
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const op::WriteDataInterleaved& cmd = m_cmds[step].u_cmd.writeInterleave;
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// new storage handle?
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_storageIDs.find(cmd.targetHandle) == m_storageIDs.end())
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_storageIDs[cmd.targetHandle] = genStorage(cmd.targetHandle);
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::ShaderProgram* program = genWriteInterleavedProgram(cmd.seed, cmd.evenOdd);
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Program #" << ++programFriendlyName << tcu::TestLog::EndMessage;
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *program;
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!program->isOk())
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw tcu::TestError("could not build program");
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationPrograms[step] = program;
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ_INTERLEAVE:
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const op::ReadDataInterleaved& cmd = m_cmds[step].u_cmd.readInterleave;
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_storageIDs.find(cmd.targetHandle) != m_storageIDs.end());
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::ShaderProgram* program = genReadInterleavedProgram(cmd.seed0, cmd.seed1);
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Program #" << ++programFriendlyName << tcu::TestLog::EndMessage;
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *program;
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!program->isOk())
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw tcu::TestError("could not build program");
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationPrograms[step] = program;
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationResultStorages[step] = genResultStorage();
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ_ZERO:
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const op::ReadZeroData& cmd = m_cmds[step].u_cmd.readZero;
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// new storage handle?
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_storageIDs.find(cmd.targetHandle) == m_storageIDs.end())
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_storageIDs[cmd.targetHandle] = genStorage(cmd.targetHandle);
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// program
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					glu::ShaderProgram* program = genReadZeroProgram();
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Program #" << ++programFriendlyName << tcu::TestLog::EndMessage;
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << *program;
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (!program->isOk())
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						throw tcu::TestError("could not build program");
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationPrograms[step] = program;
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_operationResultStorages[step] = genResultStorage();
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(DE_FALSE);
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::deinit (void)
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// programs
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)m_operationPrograms.size(); ++ndx)
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_operationPrograms[ndx];
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_operationPrograms.clear();
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// result storages
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)m_operationResultStorages.size(); ++ndx)
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_operationResultStorages[ndx])
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_operationResultStorages[ndx]);
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_operationResultStorages.clear();
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// storage
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::map<int, glw::GLuint>::const_iterator it = m_storageIDs.begin(); it != m_storageIDs.end(); ++it)
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_storage == STORAGE_BUFFER)
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.deleteBuffers(1, &it->second);
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_storage == STORAGE_IMAGE)
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.deleteTextures(1, &it->second);
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_storageIDs.clear();
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13313c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterCallTestCase::IterateResult InterCallTestCase::iterate (void)
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int programFriendlyName			= 0;
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int resultStorageFriendlyName	= 0;
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Running operations:" << tcu::TestLog::EndMessage;
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// run steps
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int step = 0; step < (int)m_cmds.size(); ++step)
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_cmds[step].type)
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_WRITE:				runCommand(m_cmds[step].u_cmd.write,			step,	programFriendlyName);								break;
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ:				runCommand(m_cmds[step].u_cmd.read,				step,	programFriendlyName, resultStorageFriendlyName);	break;
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_BARRIER:			runCommand(m_cmds[step].u_cmd.barrier);																		break;
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ_MULTIPLE:		runCommand(m_cmds[step].u_cmd.readMulti,		step,	programFriendlyName, resultStorageFriendlyName);	break;
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_WRITE_INTERLEAVE:	runCommand(m_cmds[step].u_cmd.writeInterleave,	step,	programFriendlyName);								break;
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ_INTERLEAVE:	runCommand(m_cmds[step].u_cmd.readInterleave,	step,	programFriendlyName, resultStorageFriendlyName);	break;
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case InterCallOperations::Command::TYPE_READ_ZERO:			runCommand(m_cmds[step].u_cmd.readZero,			step,	programFriendlyName, resultStorageFriendlyName);	break;
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(DE_FALSE);
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// read results from result buffers
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (verifyResults())
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, (std::string((m_storage == STORAGE_BUFFER) ? ("buffer") : ("image")) + " content verification failed").c_str());
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool InterCallTestCase::verifyResults (void)
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		resultBufferFriendlyName	= 0;
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	allResultsOk				= true;
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	anyResult					= false;
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Reading verifier program results" << tcu::TestLog::EndMessage;
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int step = 0; step < (int)m_cmds.size(); ++step)
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	errorFloodThreshold	= 5;
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int			numErrorsLogged		= 0;
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_operationResultStorages[step])
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const void*				mapped	= DE_NULL;
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::vector<deInt32>	results	(m_invocationGridSize * m_invocationGridSize);
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					error	= false;
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			anyResult = true;
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_operationResultStorages[step]);
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			mapped = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_invocationGridSize * m_invocationGridSize * sizeof(deUint32), GL_MAP_READ_BIT);
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "map buffer");
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// copy to properly aligned array
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemcpy(&results[0], mapped, m_invocationGridSize * m_invocationGridSize * sizeof(deUint32));
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER) != GL_TRUE)
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("memory map store corrupted");
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// check the results
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < (int)results.size(); ++ndx)
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (results[ndx] != 1)
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error = true;
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (numErrorsLogged == 0)
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.getLog() << tcu::TestLog::Message << "Result storage #" << ++resultBufferFriendlyName << " failed, got unexpected values.\n" << tcu::TestLog::EndMessage;
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (numErrorsLogged++ < errorFloodThreshold)
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.getLog() << tcu::TestLog::Message << "	Error at index " << ndx << ": expected 1, got " << results[ndx] << ".\n" << tcu::TestLog::EndMessage;
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						// after N errors, no point continuing verification
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.getLog() << tcu::TestLog::Message << "	-- too many errors, skipping verification --\n" << tcu::TestLog::EndMessage;
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (error)
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				allResultsOk = false;
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Result storage #" << ++resultBufferFriendlyName << " ok." << tcu::TestLog::EndMessage;
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(anyResult);
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(anyResult);
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return allResultsOk;
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::WriteData& cmd, int stepNdx, int& programFriendlyName)
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Running program #" << ++programFriendlyName << " to write " << ((m_storage == STORAGE_BUFFER) ? ("buffer") : ("image")) << " #" << cmd.targetHandle << ".\n"
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Dispatch size: " << m_invocationGridSize << "x" << m_invocationGridSize << "."
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_operationPrograms[stepNdx]->getProgram());
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set destination
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle]);
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storageIDs[cmd.targetHandle]);
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind destination buffer");
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle]);
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(0, m_storageIDs[cmd.targetHandle], 0, GL_FALSE, 0, (m_useAtomic) ? (GL_READ_WRITE) : (GL_WRITE_ONLY), (m_formatInteger) ? (GL_R32I) : (GL_R32F));
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind destination image");
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// calc
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.dispatchCompute(m_invocationGridSize, m_invocationGridSize, 1);
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "dispatch write");
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::ReadData& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName)
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	runSingleRead(cmd.targetHandle, stepNdx, programFriendlyName, resultStorageFriendlyName);
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::Barrier& cmd)
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(cmd);
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Memory Barrier\n\tbits = GL_SHADER_STORAGE_BARRIER_BIT" << tcu::TestLog::EndMessage;
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.memoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Memory Barrier\n\tbits = GL_SHADER_IMAGE_ACCESS_BARRIER_BIT" << tcu::TestLog::EndMessage;
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::ReadMultipleData& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName)
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Running program #" << ++programFriendlyName << " to verify " << ((m_storage == STORAGE_BUFFER) ? ("buffers") : ("images")) << " #" << cmd.targetHandle0 << " and #" << cmd.targetHandle1 << ".\n"
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Writing results to result storage #" << ++resultStorageFriendlyName << ".\n"
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Dispatch size: " << m_invocationGridSize << "x" << m_invocationGridSize << "."
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_operationPrograms[stepNdx]->getProgram());
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set sources
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle0]);
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle1]);
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storageIDs[cmd.targetHandle0]);
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storageIDs[cmd.targetHandle1]);
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind source buffers");
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle0]);
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle1]);
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(1, m_storageIDs[cmd.targetHandle0], 0, GL_FALSE, 0, (m_useAtomic) ? (GL_READ_WRITE) : (GL_READ_ONLY), (m_formatInteger) ? (GL_R32I) : (GL_R32F));
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(2, m_storageIDs[cmd.targetHandle1], 0, GL_FALSE, 0, (m_useAtomic) ? (GL_READ_WRITE) : (GL_READ_ONLY), (m_formatInteger) ? (GL_R32I) : (GL_R32F));
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind source images");
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set destination
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_operationResultStorages[stepNdx]);
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_operationResultStorages[stepNdx]);
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind result buffer");
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// calc
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.dispatchCompute(m_invocationGridSize, m_invocationGridSize, 1);
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "dispatch read multi");
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::WriteDataInterleaved& cmd, int stepNdx, int& programFriendlyName)
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Running program #" << ++programFriendlyName << " to write " << ((m_storage == STORAGE_BUFFER) ? ("buffer") : ("image")) << " #" << cmd.targetHandle << ".\n"
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Writing to every " << ((cmd.evenOdd) ? ("even") : ("odd")) << " " << ((m_storage == STORAGE_BUFFER) ? ("element") : ("column")) << ".\n"
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Dispatch size: " << m_invocationGridSize / 2 << "x" << m_invocationGridSize << "."
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_operationPrograms[stepNdx]->getProgram());
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set destination
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle]);
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storageIDs[cmd.targetHandle]);
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind destination buffer");
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[cmd.targetHandle]);
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(0, m_storageIDs[cmd.targetHandle], 0, GL_FALSE, 0, (m_useAtomic) ? (GL_READ_WRITE) : (GL_WRITE_ONLY), (m_formatInteger) ? (GL_R32I) : (GL_R32F));
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind destination image");
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// calc
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.dispatchCompute(m_invocationGridSize / 2, m_invocationGridSize, 1);
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "dispatch write");
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::ReadDataInterleaved& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName)
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	runSingleRead(cmd.targetHandle, stepNdx, programFriendlyName, resultStorageFriendlyName);
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runCommand (const op::ReadZeroData& cmd, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName)
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	runSingleRead(cmd.targetHandle, stepNdx, programFriendlyName, resultStorageFriendlyName);
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InterCallTestCase::runSingleRead (int targetHandle, int stepNdx, int& programFriendlyName, int& resultStorageFriendlyName)
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Running program #" << ++programFriendlyName << " to verify " << ((m_storage == STORAGE_BUFFER) ? ("buffer") : ("image")) << " #" << targetHandle << ".\n"
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Writing results to result storage #" << ++resultStorageFriendlyName << ".\n"
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	Dispatch size: " << m_invocationGridSize << "x" << m_invocationGridSize << "."
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_operationPrograms[stepNdx]->getProgram());
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set source
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[targetHandle]);
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storageIDs[targetHandle]);
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind source buffer");
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_storageIDs[targetHandle]);
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(1, m_storageIDs[targetHandle], 0, GL_FALSE, 0, (m_useAtomic) ? (GL_READ_WRITE) : (GL_READ_ONLY), (m_formatInteger) ? (GL_R32I) : (GL_R32F));
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "bind source image");
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// set destination
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_operationResultStorages[stepNdx]);
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_operationResultStorages[stepNdx]);
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind result buffer");
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// calc
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.dispatchCompute(m_invocationGridSize, m_invocationGridSize, 1);
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "dispatch read");
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglw::GLuint InterCallTestCase::genStorage (int friendlyName)
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		numElements		= m_invocationGridSize * m_invocationGridSize * m_perInvocationSize;
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		bufferSize		= numElements * ((m_formatInteger) ? (sizeof(deInt32)) : (sizeof(glw::GLfloat)));
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLuint		retVal			= 0;
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Creating buffer #" << friendlyName << ", size " << bufferSize << " bytes." << tcu::TestLog::EndMessage;
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &retVal);
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, retVal);
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_formatInteger)
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::vector<deUint32> zeroBuffer(numElements, 0);
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &zeroBuffer[0], GL_STATIC_DRAW);
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::vector<float> zeroBuffer(numElements, 0.0f);
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &zeroBuffer[0], GL_STATIC_DRAW);
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffer");
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	imageWidth	= m_invocationGridSize;
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	imageHeight	= m_invocationGridSize * m_perInvocationSize;
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLuint	retVal		= 0;
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Creating image #" << friendlyName << ", size " << imageWidth << "x" << imageHeight
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< ", internalformat = " << ((m_formatInteger) ? ("r32i") : ("r32f"))
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< ", size = " << (imageWidth*imageHeight*sizeof(deUint32)) << " bytes."
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndMessage;
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genTextures(1, &retVal);
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindTexture(GL_TEXTURE_2D, retVal);
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_formatInteger)
16708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, imageWidth, imageHeight);
16718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else
16728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32F, imageWidth, imageHeight);
16738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
16748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
16758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
16768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen image");
16778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
16788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		m_testCtx.getLog()
16798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			<< tcu::TestLog::Message
16808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			<< "Filling image with 0"
16818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			<< tcu::TestLog::EndMessage;
16828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
16838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (m_formatInteger)
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const std::vector<deInt32> zeroBuffer(imageWidth * imageHeight, 0);
16868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageWidth, imageHeight, GL_RED_INTEGER, GL_INT, &zeroBuffer[0]);
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::vector<float> zeroBuffer(imageWidth * imageHeight, 0.0f);
16918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageWidth, imageHeight, GL_RED, GL_FLOAT, &zeroBuffer[0]);
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "specify image contents");
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return retVal;
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglw::GLuint InterCallTestCase::genResultStorage (void)
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLuint				retVal	= 0;
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers(1, &retVal);
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, retVal);
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_SHADER_STORAGE_BUFFER, m_invocationGridSize * m_invocationGridSize * sizeof(deUint32), DE_NULL, GL_STATIC_DRAW);
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffer");
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return retVal;
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* InterCallTestCase::genWriteProgram (int seed)
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1) in;\n";
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=0, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer\n"
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_out;\n";
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=0) " << ((m_useAtomic) ? ("coherent ") : ("writeonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageOut;\n";
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "\n"
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	uvec3 size    = gl_NumWorkGroups * gl_WorkGroupSize;\n"
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx  = int(size.x * size.y * gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x);\n"
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Write to buffer/image m_perInvocationSize elements
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int writeNdx = 0; writeNdx < m_perInvocationSize; ++writeNdx)
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	atomicExchange(";
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	";
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "sb_out.values[(groupNdx + " << seed + writeNdx*m_invocationGridSize*m_invocationGridSize << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize << "]";
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << ", " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << " = " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx);\n";
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int writeNdx = 0; writeNdx < m_perInvocationSize; ++writeNdx)
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	imageAtomicExchange";
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	imageStore";
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "(u_imageOut, ivec2((int(gl_GlobalInvocationID.x) + " << (seed + writeNdx*100) << ") % " << m_invocationGridSize << ", int(gl_GlobalInvocationID.y) + " << writeNdx*m_invocationGridSize << "), ";
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << ((m_formatInteger) ? ("ivec4(int(groupNdx), 0, 0, 0)") : ("vec4(float(groupNdx), 0.0, 0.0, 0.0)")) << ");\n";
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "}\n";
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(buf.str()));
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* InterCallTestCase::genReadProgram (int seed)
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1) in;\n";
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=1, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer\n"
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_in;\n";
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=1) " << ((m_useAtomic) ? ("coherent ") : ("readonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageIn;\n";
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "layout(binding=0, std430) buffer ResultBuffer\n"
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp int resultOk[];\n"
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_result;\n"
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx = int(size.x * size.y * gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x);\n"
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	" << ((m_formatInteger) ? ("int") : ("float")) << " zero = " << ((m_formatInteger) ? ("0") : ("0.0")) << ";\n"
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	bool allOk = true;\n"
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify data
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
18248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
18258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (!m_useAtomic)
18268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				buf << "	allOk = allOk && (sb_in.values[(groupNdx + "
18278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< seed + readNdx*m_invocationGridSize*m_invocationGridSize << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize << "] == "
18288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
18298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			else
18308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				buf << "	allOk = allOk && (atomicExchange(sb_in.values[(groupNdx + "
18318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< seed + readNdx*m_invocationGridSize*m_invocationGridSize << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize << "], zero) == "
18328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
18338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
18388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
18398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (!m_useAtomic)
18408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				buf	<< "	allOk = allOk && (imageLoad(u_imageIn, ivec2((gl_GlobalInvocationID.x + "
18418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< (seed + readNdx*100) << "u) % " << m_invocationGridSize << "u, gl_GlobalInvocationID.y + " << readNdx*m_invocationGridSize << "u)).x == "
18428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
18438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			else
18448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				buf << "	allOk = allOk && (imageAtomicExchange(u_imageIn, ivec2((gl_GlobalInvocationID.x + "
18458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< (seed + readNdx*100) << "u) % " << m_invocationGridSize << "u, gl_GlobalInvocationID.y + " << readNdx*m_invocationGridSize << "u), zero) == "
18468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					<< ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
18478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "	sb_result.resultOk[groupNdx] = (allOk) ? (1) : (0);\n"
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(buf.str()));
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* InterCallTestCase::genReadMultipleProgram (int seed0, int seed1)
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1) in;\n";
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=1, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer0\n"
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_in0;\n"
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "layout(binding=2, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer1\n"
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_in1;\n";
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=1) " << ((m_useAtomic) ? ("coherent ") : ("readonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageIn0;\n"
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=2) " << ((m_useAtomic) ? ("coherent ") : ("readonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageIn1;\n";
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "layout(binding=0, std430) buffer ResultBuffer\n"
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp int resultOk[];\n"
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_result;\n"
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx = int(size.x * size.y * gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x);\n"
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	" << ((m_formatInteger) ? ("int") : ("float")) << " zero = " << ((m_formatInteger) ? ("0") : ("0.0")) << ";\n"
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	bool allOk = true;\n"
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify data
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "	allOk = allOk && (" << ((m_useAtomic) ? ("atomicExchange(") : ("")) << "sb_in0.values[(groupNdx + " << seed0 + readNdx*m_invocationGridSize*m_invocationGridSize << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize << "]" << ((m_useAtomic) ? (", zero)") : ("")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n"
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "	allOk = allOk && (" << ((m_useAtomic) ? ("atomicExchange(") : ("")) << "sb_in1.values[(groupNdx + " << seed1 + readNdx*m_invocationGridSize*m_invocationGridSize << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize << "]" << ((m_useAtomic) ? (", zero)") : ("")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
19068852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			buf << "	allOk = allOk && (" << ((m_useAtomic) ? ("imageAtomicExchange") : ("imageLoad")) << "(u_imageIn0, ivec2((gl_GlobalInvocationID.x + " << (seed0 + readNdx*100) << "u) % " << m_invocationGridSize << "u, gl_GlobalInvocationID.y + " << readNdx*m_invocationGridSize << "u)" << ((m_useAtomic) ? (", zero)") : (").x")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n"
19078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				<< "	allOk = allOk && (" << ((m_useAtomic) ? ("imageAtomicExchange") : ("imageLoad")) << "(u_imageIn1, ivec2((gl_GlobalInvocationID.x + " << (seed1 + readNdx*100) << "u) % " << m_invocationGridSize << "u, gl_GlobalInvocationID.y + " << readNdx*m_invocationGridSize << "u)" << ((m_useAtomic) ? (", zero)") : (").x")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "	sb_result.resultOk[groupNdx] = (allOk) ? (1) : (0);\n"
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(buf.str()));
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* InterCallTestCase::genWriteInterleavedProgram (int seed, bool evenOdd)
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1) in;\n";
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=0, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer\n"
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_out;\n";
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=0) " << ((m_useAtomic) ? ("coherent ") : ("writeonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageOut;\n";
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "\n"
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	uvec3 size    = gl_NumWorkGroups * gl_WorkGroupSize;\n"
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx  = int(size.x * size.y * gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x);\n"
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Write to buffer/image m_perInvocationSize elements
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int writeNdx = 0; writeNdx < m_perInvocationSize; ++writeNdx)
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	atomicExchange(";
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	";
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "sb_out.values[((groupNdx + " << seed + writeNdx*m_invocationGridSize*m_invocationGridSize / 2 << ") % " << m_invocationGridSize*m_invocationGridSize / 2 * m_perInvocationSize  << ") * 2 + " << ((evenOdd) ? (0) : (1)) << "]";
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << ", " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "= " << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx);\n";
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int writeNdx = 0; writeNdx < m_perInvocationSize; ++writeNdx)
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	imageAtomicExchange";
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << "	imageStore";
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "(u_imageOut, ivec2(((int(gl_GlobalInvocationID.x) + " << (seed + writeNdx*100) << ") % " << m_invocationGridSize / 2 << ") * 2 + " << ((evenOdd) ? (0) : (1)) << ", int(gl_GlobalInvocationID.y) + " << writeNdx*m_invocationGridSize << "), ";
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_useAtomic)
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << ((m_formatInteger) ? ("int") : ("float")) << "(groupNdx));\n";
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				buf << ((m_formatInteger) ? ("ivec4(int(groupNdx), 0, 0, 0)") : ("vec4(float(groupNdx), 0.0, 0.0, 0.0)")) << ");\n";
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "}\n";
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(buf.str()));
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* InterCallTestCase::genReadInterleavedProgram (int seed0, int seed1)
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1) in;\n";
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=1, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer\n"
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_in;\n";
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=1) " << ((m_useAtomic) ? ("coherent ") : ("readonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageIn;\n";
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "layout(binding=0, std430) buffer ResultBuffer\n"
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp int resultOk[];\n"
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_result;\n"
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx = int(size.x * size.y * gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x);\n"
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int interleavedGroupNdx = int((size.x >> 1U) * size.y * gl_GlobalInvocationID.z + (size.x >> 1U) * gl_GlobalInvocationID.y + (gl_GlobalInvocationID.x >> 1U));\n"
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	" << ((m_formatInteger) ? ("int") : ("float")) << " zero = " << ((m_formatInteger) ? ("0") : ("0.0")) << ";\n"
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	bool allOk = true;\n"
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify data
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	if (groupNdx % 2 == 0)\n"
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	{\n";
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "		allOk = allOk && ("
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? ("atomicExchange(") : ("")) << "sb_in.values[((interleavedGroupNdx + " << seed0 + readNdx*m_invocationGridSize*m_invocationGridSize / 2 << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize / 2 << ") * 2 + 0]"
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? (", zero)") : ("")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(interleavedGroupNdx));\n";
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	}\n"
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	else\n"
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	{\n";
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "		allOk = allOk && ("
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? ("atomicExchange(") : ("")) << "sb_in.values[((interleavedGroupNdx + " << seed1 + readNdx*m_invocationGridSize*m_invocationGridSize / 2 << ") % " << m_invocationGridSize*m_invocationGridSize*m_perInvocationSize / 2 << ") * 2 + 1]"
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? (", zero)") : ("")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(interleavedGroupNdx));\n";
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	}\n";
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	if (groupNdx % 2 == 0)\n"
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	{\n";
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "		allOk = allOk && ("
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? ("imageAtomicExchange") : ("imageLoad"))
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "(u_imageIn, ivec2(((int(gl_GlobalInvocationID.x >> 1U) + " << (seed0 + readNdx*100) << ") % " << m_invocationGridSize / 2 << ") * 2 + 0, int(gl_GlobalInvocationID.y) + " << readNdx*m_invocationGridSize << ")"
20478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				<< ((m_useAtomic) ? (", zero)") : (").x")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(interleavedGroupNdx));\n";
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	}\n"
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	else\n"
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	{\n";
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "		allOk = allOk && ("
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? ("imageAtomicExchange") : ("imageLoad"))
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "(u_imageIn, ivec2(((int(gl_GlobalInvocationID.x >> 1U) + " << (seed1 + readNdx*100) << ") % " << m_invocationGridSize / 2 << ") * 2 + 1, int(gl_GlobalInvocationID.y) + " << readNdx*m_invocationGridSize << ")"
20558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				<< ((m_useAtomic) ? (", zero)") : (").x")) << " == " << ((m_formatInteger) ? ("int") : ("float")) << "(interleavedGroupNdx));\n";
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	}\n";
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "	sb_result.resultOk[groupNdx] = (allOk) ? (1) : (0);\n"
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(buf.str()));
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram*	InterCallTestCase::genReadZeroProgram (void)
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			useImageAtomics = m_useAtomic && m_storage == STORAGE_IMAGE;
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "#version 310 es\n"
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((useImageAtomics) ? ("#extension GL_OES_shader_image_atomic : require\n") : (""))
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1) in;\n";
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(binding=1, std430) " << ((m_useAtomic) ? ("coherent ") : ("")) << "buffer Buffer\n"
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "{\n"
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	highp " << ((m_formatInteger) ? ("int") : ("float")) << " values[];\n"
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "} sb_in;\n";
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "layout(" << ((m_formatInteger) ? ("r32i") : ("r32f")) << ", binding=1) " << ((m_useAtomic) ? ("coherent ") : ("readonly ")) << "uniform highp " << ((m_formatInteger) ? ("iimage2D") : ("image2D")) << " u_imageIn;\n";
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "layout(binding=0, std430) buffer ResultBuffer\n"
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp int resultOk[];\n"
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_result;\n"
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main (void)\n"
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	int groupNdx = int(size.x * size.y * gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x);\n"
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	" << ((m_formatInteger) ? ("int") : ("float")) << " anything = " << ((m_formatInteger) ? ("5") : ("5.0")) << ";\n"
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	bool allOk = true;\n"
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n";
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify data
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_storage == STORAGE_BUFFER)
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "	allOk = allOk && ("
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? ("atomicExchange(") : ("")) << "sb_in.values[groupNdx * " << m_perInvocationSize << " + " << readNdx << "]"
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_useAtomic) ? (", anything)") : ("")) << " == " << ((m_formatInteger) ? ("0") : ("0.0")) << ");\n";
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_storage == STORAGE_IMAGE)
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < m_perInvocationSize; ++readNdx)
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf << "	allOk = allOk && ("
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< ((m_useAtomic) ? ("imageAtomicExchange") : ("imageLoad")) << "(u_imageIn, ivec2(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y + " << (readNdx*m_invocationGridSize) << "u)"
21138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			<< ((m_useAtomic) ? (", anything)") : (").x")) << " == " << ((m_formatInteger) ? ("0") : ("0.0")) << ");\n";
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf << "	sb_result.resultOk[groupNdx] = (allOk) ? (1) : (0);\n"
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(buf.str()));
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SSBOConcurrentAtomicCase : public TestCase
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							SSBOConcurrentAtomicCase	(Context& context, const char* name, const char* description, int numCalls, int workSize);
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~SSBOConcurrentAtomicCase	(void);
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init						(void);
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit						(void);
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate						(void);
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genComputeSource			(void) const;
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numCalls;
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_workSize;
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_program;
21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_bufferID;
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32>	m_intermediateResultBuffers;
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21453c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySSBOConcurrentAtomicCase::SSBOConcurrentAtomicCase (Context& context, const char* name, const char* description, int numCalls, int workSize)
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, description)
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numCalls	(numCalls)
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workSize	(workSize)
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program		(DE_NULL)
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bufferID	(DE_NULL)
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21543c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySSBOConcurrentAtomicCase::~SSBOConcurrentAtomicCase (void)
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SSBOConcurrentAtomicCase::init (void)
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32>	zeroData			(m_workSize, 0);
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen buffers
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers(1, &m_bufferID);
21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_bufferID);
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(deUint32) * m_workSize, &zeroData[0], GL_DYNAMIC_COPY);
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_numCalls; ++ndx)
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32 buffer = 0;
21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &buffer);
21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(deUint32) * m_workSize, &zeroData[0], GL_DYNAMIC_COPY);
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_intermediateResultBuffers.push_back(buffer);
21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffers");
21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen program
21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genComputeSource()));
21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("could not build program");
21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SSBOConcurrentAtomicCase::deinit (void)
21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_bufferID)
21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufferID);
21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_bufferID = 0;
21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)m_intermediateResultBuffers.size(); ++ndx)
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_intermediateResultBuffers[ndx]);
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_intermediateResultBuffers.clear();
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult SSBOConcurrentAtomicCase::iterate (void)
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			sumValue		= (deUint32)(m_numCalls * (m_numCalls + 1) / 2);
22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<int>		deltas;
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// generate unique deltas
22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateShuffledRamp(m_numCalls, deltas);
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// invoke program N times, each with a different delta
22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int deltaLocation = gl.getUniformLocation(m_program->getProgram(), "u_atomicDelta");
22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message
22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Running shader " << m_numCalls << " times.\n"
22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Num groups = (" << m_workSize << ", 1, 1)\n"
22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Setting u_atomicDelta to a unique value for each call.\n"
22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndMessage;
22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (deltaLocation == -1)
22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("u_atomicDelta location was -1");
22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(m_program->getProgram());
22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_bufferID);
22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog()
22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::Message
22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "Call " << callNdx << ": u_atomicDelta = " << deltas[callNdx]
22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::EndMessage;
22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform1ui(deltaLocation, deltas[callNdx]);
22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_intermediateResultBuffers[callNdx]);
22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.dispatchCompute(m_workSize, 1, 1);
22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "post dispatch");
22453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify result
22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32> result;
22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying work buffer, it should be filled with value " << sumValue << tcu::TestLog::EndMessage;
22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_bufferID);
22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		readBuffer(gl, GL_SHADER_STORAGE_BUFFER, m_workSize, result);
22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < m_workSize; ++ndx)
22573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (result[ndx] != sumValue)
22593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Work buffer error, at index " << ndx << " expected value " << (sumValue) << ", got " << result[ndx] << "\n"
22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Work buffer contains invalid values."
22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents invalid");
22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Work buffer contents are valid." << tcu::TestLog::EndMessage;
22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// verify steps
22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<std::vector<deUint32> >	intermediateResults	(m_numCalls);
22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32>				valueChain			(m_numCalls);
22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying intermediate results. " << tcu::TestLog::EndMessage;
22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// collect results
22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_intermediateResultBuffers[callNdx]);
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			readBuffer(gl, GL_SHADER_STORAGE_BUFFER, m_workSize, intermediateResults[callNdx]);
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// verify values
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valueNdx = 0; valueNdx < m_workSize; ++valueNdx)
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			invalidOperationNdx;
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	errorDelta;
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	errorExpected;
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// collect result chain for each element
22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				valueChain[callNdx] = intermediateResults[callNdx][valueNdx];
23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// check there exists a path from 0 to sumValue using each addition once
23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// decompose cumulative results to addition operations (all additions positive => this works)
23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::sort(valueChain.begin(), valueChain.end());
23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// validate chain
23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!validateSortedAtomicRampAdditionValueChain(valueChain, sumValue, invalidOperationNdx, errorDelta, errorExpected))
23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Intermediate buffer error, at value index " << valueNdx << ", applied operation index " << invalidOperationNdx << ", value was increased by " << errorDelta << ", but expected " << errorExpected << ".\n"
23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Intermediate buffer contains invalid values. Values at index " << valueNdx << "\n"
23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int logCallNdx = 0; logCallNdx < m_numCalls; ++logCallNdx)
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Value[" << logCallNdx << "] = " << intermediateResults[logCallNdx][valueNdx] << tcu::TestLog::EndMessage;
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Result = " << sumValue << tcu::TestLog::EndMessage;
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents invalid");
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Intermediate buffers are valid." << tcu::TestLog::EndMessage;
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string SSBOConcurrentAtomicCase::genComputeSource (void) const
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 1, std430) writeonly buffer IntermediateResults\n"
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint values[" << m_workSize << "];\n"
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_ires;\n"
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 2, std430) volatile buffer WorkBuffer\n"
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint values[" << m_workSize << "];\n"
23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_work;\n"
23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "uniform highp uint u_atomicDelta;\n"
23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint invocationIndex = gl_GlobalInvocationID.x;\n"
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	sb_ires.values[invocationIndex] = atomicAdd(sb_work.values[invocationIndex], u_atomicDelta);\n"
23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ConcurrentAtomicCounterCase : public TestCase
23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							ConcurrentAtomicCounterCase		(Context& context, const char* name, const char* description, int numCalls, int workSize);
23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~ConcurrentAtomicCounterCase	(void);
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init							(void);
23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit							(void);
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate							(void);
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genComputeSource				(bool evenOdd) const;
23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numCalls;
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_workSize;
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_evenProgram;
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_oddProgram;
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_counterBuffer;
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_intermediateResultBuffer;
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23793c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConcurrentAtomicCounterCase::ConcurrentAtomicCounterCase (Context& context, const char* name, const char* description, int numCalls, int workSize)
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, description)
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numCalls				(numCalls)
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workSize				(workSize)
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_evenProgram				(DE_NULL)
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_oddProgram				(DE_NULL)
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_counterBuffer			(DE_NULL)
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_intermediateResultBuffer(DE_NULL)
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23903c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConcurrentAtomicCounterCase::~ConcurrentAtomicCounterCase (void)
23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentAtomicCounterCase::init (void)
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<deUint32>	zeroData	(m_numCalls * m_workSize, 0);
23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen buffer
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers(1, &m_counterBuffer);
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_counterBuffer);
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(deUint32), &zeroData[0], GL_DYNAMIC_COPY);
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers(1, &m_intermediateResultBuffer);
24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_intermediateResultBuffer);
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(deUint32) * m_numCalls * m_workSize, &zeroData[0], GL_DYNAMIC_COPY);
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffers");
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen programs
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "EvenProgram", "Even program");
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_evenProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genComputeSource(true)));
24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_evenProgram;
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_evenProgram->isOk())
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("could not build program");
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "OddProgram", "Odd program");
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_oddProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genComputeSource(false)));
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_oddProgram;
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_oddProgram->isOk())
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("could not build program");
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentAtomicCounterCase::deinit (void)
24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_counterBuffer)
24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_counterBuffer);
24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_counterBuffer = 0;
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_intermediateResultBuffer)
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_intermediateResultBuffer);
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_intermediateResultBuffer = 0;
24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_evenProgram;
24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_evenProgram = DE_NULL;
24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_oddProgram;
24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_oddProgram = DE_NULL;
24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult ConcurrentAtomicCounterCase::iterate (void)
24533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// invoke program N times, each with a different delta
24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int evenCallNdxLocation	= gl.getUniformLocation(m_evenProgram->getProgram(), "u_callNdx");
24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int oddCallNdxLocation	= gl.getUniformLocation(m_oddProgram->getProgram(), "u_callNdx");
24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message
24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Running shader pair (even & odd) " << m_numCalls << " times.\n"
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Num groups = (" << m_workSize << ", 1, 1)\n"
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndMessage;
24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (evenCallNdxLocation == -1)
24683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("u_callNdx location was -1");
24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (oddCallNdxLocation == -1)
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("u_callNdx location was -1");
24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_intermediateResultBuffer);
24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counterBuffer);
24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram(m_evenProgram->getProgram());
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform1ui(evenCallNdxLocation, (deUint32)callNdx);
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.dispatchCompute(m_workSize, 1, 1);
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram(m_oddProgram->getProgram());
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform1ui(oddCallNdxLocation, (deUint32)callNdx);
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.dispatchCompute(m_workSize, 1, 1);
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "post dispatch");
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify result
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32 result;
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying work buffer, it should be " << m_numCalls*m_workSize << tcu::TestLog::EndMessage;
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counterBuffer);
24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result = readBufferUint32(gl, GL_ATOMIC_COUNTER_BUFFER);
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((int)result != m_numCalls*m_workSize)
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog()
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::Message
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "Counter buffer error, expected value " << (m_numCalls*m_workSize) << ", got " << result << "\n"
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::EndMessage;
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents invalid");
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return STOP;
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Counter buffer is valid." << tcu::TestLog::EndMessage;
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// verify steps
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32> intermediateResults;
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying intermediate results. " << tcu::TestLog::EndMessage;
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// collect results
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_intermediateResultBuffer);
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		readBuffer(gl, GL_SHADER_STORAGE_BUFFER, m_numCalls * m_workSize, intermediateResults);
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// verify values
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::sort(intermediateResults.begin(), intermediateResults.end());
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valueNdx = 0; valueNdx < m_workSize * m_numCalls; ++valueNdx)
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if ((int)intermediateResults[valueNdx] != valueNdx)
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Intermediate buffer error, at value index " << valueNdx << ", expected " << valueNdx << ", got " << intermediateResults[valueNdx] << ".\n"
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Intermediate buffer contains invalid values. Intermediate results:\n"
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int logCallNdx = 0; logCallNdx < m_workSize * m_numCalls; ++logCallNdx)
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Value[" << logCallNdx << "] = " << intermediateResults[logCallNdx] << tcu::TestLog::EndMessage;
25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents invalid");
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Intermediate buffers are valid." << tcu::TestLog::EndMessage;
25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ConcurrentAtomicCounterCase::genComputeSource (bool evenOdd) const
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 1, std430) writeonly buffer IntermediateResults\n"
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint values[" << m_workSize * m_numCalls << "];\n"
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_ires;\n"
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 2, offset = 0) uniform atomic_uint u_counter;\n"
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "uniform highp uint u_callNdx;\n"
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint dataNdx = u_callNdx * " << m_workSize << "u + gl_GlobalInvocationID.x;\n"
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	if ((dataNdx % 2u) == " << ((evenOdd) ? (0) : (1)) << "u)\n"
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "		sb_ires.values[dataNdx] = atomicCounterIncrement(u_counter);\n"
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ConcurrentImageAtomicCase : public TestCase
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							ConcurrentImageAtomicCase	(Context& context, const char* name, const char* description, int numCalls, int workSize);
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~ConcurrentImageAtomicCase	(void);
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init						(void);
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit						(void);
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate						(void);
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					readWorkImage				(std::vector<deUint32>& result);
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genComputeSource			(void) const;
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genImageReadSource			(void) const;
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genImageClearSource			(void) const;
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numCalls;
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_workSize;
25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_program;
25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_imageReadProgram;
25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_imageClearProgram;
25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_imageID;
26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32>	m_intermediateResultBuffers;
26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26033c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConcurrentImageAtomicCase::ConcurrentImageAtomicCase (Context& context, const char* name, const char* description, int numCalls, int workSize)
26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase				(context, name, description)
26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numCalls			(numCalls)
26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workSize			(workSize)
26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program				(DE_NULL)
26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_imageReadProgram	(DE_NULL)
26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_imageClearProgram	(DE_NULL)
26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_imageID				(DE_NULL)
26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26143c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConcurrentImageAtomicCase::~ConcurrentImageAtomicCase (void)
26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
26173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentImageAtomicCase::init (void)
26203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
26223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint32>	zeroData			(m_workSize * m_workSize, 0);
26233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic"))
26253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_OES_shader_image_atomic");
26263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen image
26283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genTextures(1, &m_imageID);
26303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTexture(GL_TEXTURE_2D, m_imageID);
26313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, m_workSize, m_workSize);
26328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
26338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
26343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "gen tex");
26353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen buffers
26373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_numCalls; ++ndx)
26393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32 buffer = 0;
26413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &buffer);
26433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
26443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(deUint32) * m_workSize * m_workSize, &zeroData[0], GL_DYNAMIC_COPY);
26453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_intermediateResultBuffers.push_back(buffer);
26473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffers");
26483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen programs
26513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genComputeSource()));
26533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
26543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
26553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("could not build program");
26563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_imageReadProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genImageReadSource()));
26583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_imageReadProgram->isOk())
26593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "ImageReadProgram", "Image read program");
26613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_imageReadProgram;
26633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("could not build program");
26643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_imageClearProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genImageClearSource()));
26673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_imageClearProgram->isOk())
26683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "ImageClearProgram", "Image read program");
26703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_imageClearProgram;
26723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("could not build program");
26733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentImageAtomicCase::deinit (void)
26773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_imageID)
26793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_imageID);
26813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_imageID = 0;
26823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)m_intermediateResultBuffers.size(); ++ndx)
26853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_intermediateResultBuffers[ndx]);
26863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_intermediateResultBuffers.clear();
26873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
26893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
26903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_imageReadProgram;
26923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_imageReadProgram = DE_NULL;
26933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_imageClearProgram;
26953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_imageClearProgram = DE_NULL;
26963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
26973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26983c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult ConcurrentImageAtomicCase::iterate (void)
26993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
27013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			sumValue		= (deUint32)(m_numCalls * (m_numCalls + 1) / 2);
27023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<int>		deltas;
27033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// generate unique deltas
27053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	generateShuffledRamp(m_numCalls, deltas);
27063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// clear image
27083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Clearing image contents" << tcu::TestLog::EndMessage;
27103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(m_imageClearProgram->getProgram());
27123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(2, m_imageID, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
27133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.dispatchCompute(m_workSize, m_workSize, 1);
27143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
27153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
27173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// invoke program N times, each with a different delta
27203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int deltaLocation = gl.getUniformLocation(m_program->getProgram(), "u_atomicDelta");
27223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
27243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message
27253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Running shader " << m_numCalls << " times.\n"
27263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Num groups = (" << m_workSize << ", " << m_workSize << ", 1)\n"
27273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Setting u_atomicDelta to a unique value for each call.\n"
27283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndMessage;
27293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (deltaLocation == -1)
27313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("u_atomicDelta location was -1");
27323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(m_program->getProgram());
27343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(2, m_imageID, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
27353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
27373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog()
27393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::Message
27403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "Call " << callNdx << ": u_atomicDelta = " << deltas[callNdx]
27413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::EndMessage;
27423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform1ui(deltaLocation, deltas[callNdx]);
27443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_intermediateResultBuffers[callNdx]);
27453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.dispatchCompute(m_workSize, m_workSize, 1);
27463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "post dispatch");
27493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify result
27523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32> result;
27543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying work image, it should be filled with value " << sumValue << tcu::TestLog::EndMessage;
27563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		readWorkImage(result);
27583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < m_workSize * m_workSize; ++ndx)
27603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (result[ndx] != sumValue)
27623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
27633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
27643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
27653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Work image error, at index (" << ndx % m_workSize << ", " << ndx / m_workSize << ") expected value " << (sumValue) << ", got " << result[ndx] << "\n"
27663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Work image contains invalid values."
27673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
27683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image contents invalid");
27703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
27713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
27723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Work image contents are valid." << tcu::TestLog::EndMessage;
27753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// verify steps
27783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<std::vector<deUint32> >	intermediateResults	(m_numCalls);
27803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32>				valueChain			(m_numCalls);
27813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<deUint32>				chainDelta			(m_numCalls);
27823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying intermediate results. " << tcu::TestLog::EndMessage;
27843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// collect results
27863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
27883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_intermediateResultBuffers[callNdx]);
27903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			readBuffer(gl, GL_SHADER_STORAGE_BUFFER, m_workSize * m_workSize, intermediateResults[callNdx]);
27913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// verify values
27943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int valueNdx = 0; valueNdx < m_workSize; ++valueNdx)
27963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			invalidOperationNdx;
27983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	errorDelta;
27993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32	errorExpected;
28003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// collect result chain for each element
28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				valueChain[callNdx] = intermediateResults[callNdx][valueNdx];
28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// check there exists a path from 0 to sumValue using each addition once
28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// decompose cumulative results to addition operations (all additions positive => this works)
28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::sort(valueChain.begin(), valueChain.end());
28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				chainDelta[callNdx] = ((callNdx + 1 == m_numCalls) ? (sumValue) : (valueChain[callNdx+1])) - valueChain[callNdx];
28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// chainDelta contains now the actual additions applied to the value
28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::sort(chainDelta.begin(), chainDelta.end());
28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// validate chain
28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!validateSortedAtomicRampAdditionValueChain(valueChain, sumValue, invalidOperationNdx, errorDelta, errorExpected))
28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Intermediate buffer error, at index (" << valueNdx % m_workSize << ", " << valueNdx / m_workSize << "), applied operation index "
28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< invalidOperationNdx << ", value was increased by " << errorDelta << ", but expected " << errorExpected << ".\n"
28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Intermediate buffer contains invalid values. Values at index (" << valueNdx % m_workSize << ", " << valueNdx / m_workSize << ")\n"
28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int logCallNdx = 0; logCallNdx < m_numCalls; ++logCallNdx)
28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << tcu::TestLog::Message << "Value[" << logCallNdx << "] = " << intermediateResults[logCallNdx][valueNdx] << tcu::TestLog::EndMessage;
28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Result = " << sumValue << tcu::TestLog::EndMessage;
28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents invalid");
28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return STOP;
28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Intermediate buffers are valid." << tcu::TestLog::EndMessage;
28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentImageAtomicCase::readWorkImage (std::vector<deUint32>& result)
28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Buffer				resultBuffer	(m_context.getRenderContext());
28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read image to an ssbo
28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const std::vector<deUint32> zeroData(m_workSize*m_workSize, 0);
28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *resultBuffer);
28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_SHADER_STORAGE_BUFFER, (int)(sizeof(deUint32) * m_workSize * m_workSize), &zeroData[0], GL_DYNAMIC_COPY);
28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(m_imageReadProgram->getProgram());
28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, *resultBuffer);
28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindImageTexture(2, m_imageID, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.dispatchCompute(m_workSize, m_workSize, 1);
28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "read");
28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read ssbo
28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void* ptr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (int)(sizeof(deUint32) * m_workSize * m_workSize), GL_MAP_READ_BIT);
28683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "map");
28693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!ptr)
28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("mapBufferRange returned NULL");
28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result.resize(m_workSize * m_workSize);
28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		memcpy(&result[0], ptr, sizeof(deUint32) * m_workSize * m_workSize);
28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER) == GL_FALSE)
28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("unmapBuffer returned false");
28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ConcurrentImageAtomicCase::genComputeSource (void) const
28823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "#extension GL_OES_shader_image_atomic : require\n"
28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 1, std430) writeonly buffer IntermediateResults\n"
28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint values[" << m_workSize * m_workSize << "];\n"
28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_ires;\n"
28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
28948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		<< "layout (binding = 2, r32ui) volatile uniform highp uimage2D u_workImage;\n"
28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "uniform highp uint u_atomicDelta;\n"
28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint invocationIndex = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * uint(" << m_workSize <<");\n"
29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	sb_ires.values[invocationIndex] = imageAtomicAdd(u_workImage, ivec2(gl_GlobalInvocationID.xy), u_atomicDelta);\n"
29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ConcurrentImageAtomicCase::genImageReadSource (void) const
29073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 1, std430) writeonly buffer ImageValues\n"
29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint values[" << m_workSize * m_workSize << "];\n"
29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_res;\n"
29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
29188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		<< "layout (binding = 2, r32ui) readonly uniform highp uimage2D u_workImage;\n"
29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint invocationIndex = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * uint(" << m_workSize <<");\n"
29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	sb_res.values[invocationIndex] = imageLoad(u_workImage, ivec2(gl_GlobalInvocationID.xy)).x;\n"
29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ConcurrentImageAtomicCase::genImageClearSource (void) const
29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
29368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		<< "layout (binding = 2, r32ui) writeonly uniform highp uimage2D u_workImage;\n"
29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	imageStore(u_workImage, ivec2(gl_GlobalInvocationID.xy), uvec4(0, 0, 0, 0));\n"
29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ConcurrentSSBOAtomicCounterMixedCase : public TestCase
29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							ConcurrentSSBOAtomicCounterMixedCase	(Context& context, const char* name, const char* description, int numCalls, int workSize);
29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~ConcurrentSSBOAtomicCounterMixedCase	(void);
29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init									(void);
29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit									(void);
29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate									(void);
29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genSSBOComputeSource					(void) const;
29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string				genAtomicCounterComputeSource			(void) const;
29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numCalls;
29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_workSize;
29623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_bufferID;
29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_ssboAtomicProgram;
29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*		m_atomicCounterProgram;
29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConcurrentSSBOAtomicCounterMixedCase::ConcurrentSSBOAtomicCounterMixedCase (Context& context, const char* name, const char* description, int numCalls, int workSize)
29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, description)
29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numCalls				(numCalls)
29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_workSize				(workSize)
29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bufferID				(DE_NULL)
29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_ssboAtomicProgram		(DE_NULL)
29733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_atomicCounterProgram	(DE_NULL)
29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// SSBO atomic XORs cancel out
29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((workSize * numCalls) % (16 * 2) == 0);
29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29793c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConcurrentSSBOAtomicCounterMixedCase::~ConcurrentSSBOAtomicCounterMixedCase (void)
29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
29823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentSSBOAtomicCounterMixedCase::init (void)
29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				zeroBuf[2]	= { 0, 0 };
29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen buffer
29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers(1, &m_bufferID);
29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_bufferID);
29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_SHADER_STORAGE_BUFFER, (int)(sizeof(deUint32) * 2), zeroBuf, GL_DYNAMIC_COPY);
29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffers");
29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen programs
29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "SSBOProgram", "SSBO atomic program");
30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_ssboAtomicProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genSSBOComputeSource()));
30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_ssboAtomicProgram;
30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_ssboAtomicProgram->isOk())
30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("could not build program");
30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection section(m_testCtx.getLog(), "AtomicCounterProgram", "Atomic counter program");
30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_atomicCounterProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genAtomicCounterComputeSource()));
30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_atomicCounterProgram;
30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_atomicCounterProgram->isOk())
30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("could not build program");
30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConcurrentSSBOAtomicCounterMixedCase::deinit (void)
30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_bufferID)
30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufferID);
30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_bufferID = 0;
30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_ssboAtomicProgram;
30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ssboAtomicProgram = DE_NULL;
30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_atomicCounterProgram;
30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_atomicCounterProgram = DE_NULL;
30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30323c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestCase::IterateResult ConcurrentSSBOAtomicCounterMixedCase::iterate (void)
30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Testing atomic counters and SSBO atomic operations with both backed by the same buffer." << tcu::TestLog::EndMessage;
30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// invoke programs N times
30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message
30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Running SSBO atomic program and atomic counter program " << m_numCalls << " times. (interleaved)\n"
30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Num groups = (" << m_workSize << ", 1, 1)\n"
30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndMessage;
30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_bufferID);
30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_bufferID);
30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int callNdx = 0; callNdx < m_numCalls; ++callNdx)
30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram(m_atomicCounterProgram->getProgram());
30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.dispatchCompute(m_workSize, 1, 1);
30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram(m_ssboAtomicProgram->getProgram());
30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.dispatchCompute(m_workSize, 1, 1);
30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "post dispatch");
30593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify result
30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32 result;
30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// XORs cancel out, only addition is left
30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying work buffer, it should be " << m_numCalls*m_workSize << tcu::TestLog::EndMessage;
30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_bufferID);
30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result = readBufferUint32(gl, GL_ATOMIC_COUNTER_BUFFER);
30703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((int)result != m_numCalls*m_workSize)
30723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog()
30743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::Message
30753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "Buffer value error, expected value " << (m_numCalls*m_workSize) << ", got " << result << "\n"
30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::EndMessage;
30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents invalid");
30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return STOP;
30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Buffer is valid." << tcu::TestLog::EndMessage;
30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ConcurrentSSBOAtomicCounterMixedCase::genSSBOComputeSource (void) const
30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
30953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 1, std430) volatile buffer WorkBuffer\n"
30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint targetValue;\n"
30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint dummy;\n"
30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "} sb_work;\n"
31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
31033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	// flip high bits\n"
31043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	highp uint mask = uint(1) << (16u + (gl_GlobalInvocationID.x % 16u));\n"
31053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	sb_work.dummy = atomicXor(sb_work.targetValue, mask);\n"
31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ConcurrentSSBOAtomicCounterMixedCase::genAtomicCounterComputeSource (void) const
31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (binding = 2, offset = 0) uniform atomic_uint u_counter;\n"
31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	atomicCounterIncrement(u_counter);\n"
31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}";
31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31303c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySynchronizationTests::SynchronizationTests (Context& context)
31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "synchronization", "Synchronization tests")
31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31353c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySynchronizationTests::~SynchronizationTests (void)
31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SynchronizationTests::init (void)
31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* const inInvocationGroup		= new tcu::TestCaseGroup(m_testCtx, "in_invocation",	"Test intra-invocation synchronization");
31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* const interInvocationGroup	= new tcu::TestCaseGroup(m_testCtx, "inter_invocation", "Test inter-invocation synchronization");
31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* const interCallGroup		= new tcu::TestCaseGroup(m_testCtx, "inter_call",       "Test inter-call synchronization");
31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(inInvocationGroup);
31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(interInvocationGroup);
31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(interCallGroup);
31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .in_invocation & .inter_invocation
31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const struct CaseConfig
31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*									namePrefix;
31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const InterInvocationTestCase::StorageType	storage;
31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int									flags;
31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} configs[] =
31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "image",			InterInvocationTestCase::STORAGE_IMAGE,		0										},
31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "image_atomic",	InterInvocationTestCase::STORAGE_IMAGE,		InterInvocationTestCase::FLAG_ATOMIC	},
31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "ssbo",			InterInvocationTestCase::STORAGE_BUFFER,	0										},
31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "ssbo_atomic",	InterInvocationTestCase::STORAGE_BUFFER,	InterInvocationTestCase::FLAG_ATOMIC	},
31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int groupNdx = 0; groupNdx < 2; ++groupNdx)
31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* const	targetGroup	= (groupNdx == 0) ? (inInvocationGroup) : (interInvocationGroup);
31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					extraFlags	= (groupNdx == 0) ? (0) : (InterInvocationTestCase::FLAG_IN_GROUP);
31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(configs); ++configNdx)
31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const target = (configs[configNdx].storage == InterInvocationTestCase::STORAGE_BUFFER) ? ("buffer") : ("image");
31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				targetGroup->addChild(new InvocationWriteReadCase(m_context,
31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  (std::string(configs[configNdx].namePrefix) + "_write_read").c_str(),
31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  (std::string("Write to ") + target + " and read it").c_str(),
31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  configs[configNdx].storage,
31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  configs[configNdx].flags | extraFlags));
31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				targetGroup->addChild(new InvocationReadWriteCase(m_context,
31803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  (std::string(configs[configNdx].namePrefix) + "_read_write").c_str(),
31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  (std::string("Read form ") + target + " and then write to it").c_str(),
31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  configs[configNdx].storage,
31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  configs[configNdx].flags | extraFlags));
31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				targetGroup->addChild(new InvocationOverWriteCase(m_context,
31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  (std::string(configs[configNdx].namePrefix) + "_overwrite").c_str(),
31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  (std::string("Write to ") + target + " twice and read it").c_str(),
31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  configs[configNdx].storage,
31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  configs[configNdx].flags | extraFlags));
31903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				targetGroup->addChild(new InvocationAliasWriteCase(m_context,
31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   (std::string(configs[configNdx].namePrefix) + "_alias_write").c_str(),
31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   (std::string("Write to aliasing ") + target + " and read it").c_str(),
31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   InvocationAliasWriteCase::TYPE_WRITE,
31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   configs[configNdx].storage,
31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   configs[configNdx].flags | extraFlags));
31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				targetGroup->addChild(new InvocationAliasWriteCase(m_context,
31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   (std::string(configs[configNdx].namePrefix) + "_alias_overwrite").c_str(),
32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   (std::string("Write to aliasing ") + target + "s and read it").c_str(),
32013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   InvocationAliasWriteCase::TYPE_OVERWRITE,
32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   configs[configNdx].storage,
32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   configs[configNdx].flags | extraFlags));
32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .inter_call
32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const withBarrierGroup		= new tcu::TestCaseGroup(m_testCtx, "with_memory_barrier", "Synchronize with memory barrier");
32113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const withoutBarrierGroup	= new tcu::TestCaseGroup(m_testCtx, "without_memory_barrier", "Synchronize without memory barrier");
32123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		interCallGroup->addChild(withBarrierGroup);
32143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		interCallGroup->addChild(withoutBarrierGroup);
32153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .with_memory_barrier
32173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			static const struct CaseConfig
32193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
32203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char*								namePrefix;
32213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const InterCallTestCase::StorageType	storage;
32223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int								flags;
32233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			} configs[] =
32243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
32253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ "image",			InterCallTestCase::STORAGE_IMAGE,	0																		},
32263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ "image_atomic",	InterCallTestCase::STORAGE_IMAGE,	InterCallTestCase::FLAG_USE_ATOMIC | InterCallTestCase::FLAG_USE_INT	},
32273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ "ssbo",			InterCallTestCase::STORAGE_BUFFER,	0																		},
32283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{ "ssbo_atomic",	InterCallTestCase::STORAGE_BUFFER,	InterCallTestCase::FLAG_USE_ATOMIC | InterCallTestCase::FLAG_USE_INT	},
32293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
32303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int seed0 = 123;
32323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int seed1 = 457;
32333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(configs); ++configNdx)
32353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
32363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char* const target = (configs[configNdx].storage == InterCallTestCase::STORAGE_BUFFER) ? ("buffer") : ("image");
32373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
32393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_write_read").c_str(),
32403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Write to ") + target + " and read it").c_str(),
32413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
32423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
32433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
32443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed0)
32453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
32463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadData::Generate(1, seed0)));
32473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
32493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_read_write").c_str(),
32503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Read from ") + target + " and then write to it").c_str(),
32513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
32523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
32533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
32543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadZeroData::Generate(1)
32553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
32563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed0)));
32573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
32593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_overwrite").c_str(),
32603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Write to ") + target + " twice and read it").c_str(),
32613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
32623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
32633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
32643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed0)
32653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
32663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed1)
32673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
32683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadData::Generate(1, seed1)));
32693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
32713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_multiple_write_read").c_str(),
32723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Write to multiple ") + target + "s and read them").c_str(),
32733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
32743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
32753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
32763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed0)
32773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(2, seed1)
32783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
32793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadMultipleData::Generate(1, seed0, 2, seed1)));
32803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
32823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_multiple_interleaved_write_read").c_str(),
32833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Write to same ") + target + " in multiple calls and read it").c_str(),
32843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
32853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
32863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
32873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteDataInterleaved::Generate(1, seed0, true)
32883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteDataInterleaved::Generate(1, seed1, false)
32893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
32903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadDataInterleaved::Generate(1, seed0, seed1)));
32913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
32933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_multiple_unrelated_write_read_ordered").c_str(),
32943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Two unrelated ") + target + " write-reads").c_str(),
32953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
32963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
32973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
32983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed0)
32993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(2, seed1)
33003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
33013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadData::Generate(1, seed0)
33023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadData::Generate(2, seed1)));
33033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				withBarrierGroup->addChild(new InterCallTestCase(m_context,
33053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string(configs[configNdx].namePrefix) + "_multiple_unrelated_write_read_non_ordered").c_str(),
33063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 (std::string("Two unrelated ") + target + " write-reads").c_str(),
33073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].storage,
33083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 configs[configNdx].flags,
33093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																 InterCallOperations()
33103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(1, seed0)
33113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::WriteData::Generate(2, seed1)
33123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::Barrier()
33133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadData::Generate(2, seed1)
33143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	<< op::ReadData::Generate(1, seed0)));
33153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
33163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// .without_memory_barrier
33183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
33193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				struct InvocationConfig
33203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
33213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const char*	name;
33223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int			count;
33233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
33243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				static const InvocationConfig ssboInvocations[] =
33263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
33273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "1k",		1024	},
33283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "4k",		4096	},
33293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "32k",	32768	},
33303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
33313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				static const InvocationConfig imageInvocations[] =
33323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
33333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "8x8",		8	},
33343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "32x32",		32	},
33353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "128x128",	128	},
33363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
33373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				static const InvocationConfig counterInvocations[] =
33383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
33393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "32",		32		},
33403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "128",	128		},
33413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{ "1k",		1024	},
33423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
33433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				static const int callCounts[] = { 2, 5, 100 };
33443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(ssboInvocations); ++invocationNdx)
33463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int callCountNdx = 0; callCountNdx < DE_LENGTH_OF_ARRAY(callCounts); ++callCountNdx)
33473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						withoutBarrierGroup->addChild(new SSBOConcurrentAtomicCase(m_context, (std::string("ssbo_atomic_dispatch_") + de::toString(callCounts[callCountNdx]) + "_calls_" + ssboInvocations[invocationNdx].name + "_invocations").c_str(),	"", callCounts[callCountNdx], ssboInvocations[invocationNdx].count));
33483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(imageInvocations); ++invocationNdx)
33503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int callCountNdx = 0; callCountNdx < DE_LENGTH_OF_ARRAY(callCounts); ++callCountNdx)
33513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						withoutBarrierGroup->addChild(new ConcurrentImageAtomicCase(m_context, (std::string("image_atomic_dispatch_") + de::toString(callCounts[callCountNdx]) + "_calls_" + imageInvocations[invocationNdx].name + "_invocations").c_str(),	"", callCounts[callCountNdx], imageInvocations[invocationNdx].count));
33523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(counterInvocations); ++invocationNdx)
33543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int callCountNdx = 0; callCountNdx < DE_LENGTH_OF_ARRAY(callCounts); ++callCountNdx)
33553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						withoutBarrierGroup->addChild(new ConcurrentAtomicCounterCase(m_context, (std::string("atomic_counter_dispatch_") + de::toString(callCounts[callCountNdx]) + "_calls_" + counterInvocations[invocationNdx].name + "_invocations").c_str(),	"", callCounts[callCountNdx], counterInvocations[invocationNdx].count));
33563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(counterInvocations); ++invocationNdx)
33583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int callCountNdx = 0; callCountNdx < DE_LENGTH_OF_ARRAY(callCounts); ++callCountNdx)
33593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						withoutBarrierGroup->addChild(new ConcurrentSSBOAtomicCounterMixedCase(m_context, (std::string("ssbo_atomic_counter_mixed_dispatch_") + de::toString(callCounts[callCountNdx]) + "_calls_" + counterInvocations[invocationNdx].name + "_invocations").c_str(),	"", callCounts[callCountNdx], counterInvocations[invocationNdx].count));
33603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
33613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
33643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
33663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
33673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
3368