1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief Shader atomic operation tests.
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "es31fShaderAtomicOpTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "gluShaderUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluProgramInterfaceQuery.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "tcuVector.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "tcuFormatUtil.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
38*35238bceSAndroid Build Coastguard Worker
39*35238bceSAndroid Build Coastguard Worker #include <algorithm>
40*35238bceSAndroid Build Coastguard Worker #include <set>
41*35238bceSAndroid Build Coastguard Worker
42*35238bceSAndroid Build Coastguard Worker namespace deqp
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker namespace gles31
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker namespace Functional
47*35238bceSAndroid Build Coastguard Worker {
48*35238bceSAndroid Build Coastguard Worker
49*35238bceSAndroid Build Coastguard Worker using std::set;
50*35238bceSAndroid Build Coastguard Worker using std::string;
51*35238bceSAndroid Build Coastguard Worker using std::vector;
52*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
53*35238bceSAndroid Build Coastguard Worker using tcu::UVec3;
54*35238bceSAndroid Build Coastguard Worker using namespace glu;
55*35238bceSAndroid Build Coastguard Worker
56*35238bceSAndroid Build Coastguard Worker template <typename T, int Size>
product(const tcu::Vector<T,Size> & v)57*35238bceSAndroid Build Coastguard Worker static inline T product(const tcu::Vector<T, Size> &v)
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker T res = v[0];
60*35238bceSAndroid Build Coastguard Worker for (int ndx = 1; ndx < Size; ndx++)
61*35238bceSAndroid Build Coastguard Worker res *= v[ndx];
62*35238bceSAndroid Build Coastguard Worker return res;
63*35238bceSAndroid Build Coastguard Worker }
64*35238bceSAndroid Build Coastguard Worker
65*35238bceSAndroid Build Coastguard Worker class ShaderAtomicOpCase : public TestCase
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker public:
68*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase(Context &context, const char *name, const char *funcName, AtomicOperandType operandType,
69*35238bceSAndroid Build Coastguard Worker DataType type, Precision precision, const UVec3 &workGroupSize);
70*35238bceSAndroid Build Coastguard Worker ~ShaderAtomicOpCase(void);
71*35238bceSAndroid Build Coastguard Worker
72*35238bceSAndroid Build Coastguard Worker void init(void);
73*35238bceSAndroid Build Coastguard Worker void deinit(void);
74*35238bceSAndroid Build Coastguard Worker IterateResult iterate(void);
75*35238bceSAndroid Build Coastguard Worker
76*35238bceSAndroid Build Coastguard Worker protected:
77*35238bceSAndroid Build Coastguard Worker virtual void getInputs(int numValues, int stride, void *inputs) const = 0;
78*35238bceSAndroid Build Coastguard Worker virtual bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
79*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const = 0;
80*35238bceSAndroid Build Coastguard Worker
81*35238bceSAndroid Build Coastguard Worker const string m_funcName;
82*35238bceSAndroid Build Coastguard Worker const AtomicOperandType m_operandType;
83*35238bceSAndroid Build Coastguard Worker const DataType m_type;
84*35238bceSAndroid Build Coastguard Worker const Precision m_precision;
85*35238bceSAndroid Build Coastguard Worker
86*35238bceSAndroid Build Coastguard Worker const UVec3 m_workGroupSize;
87*35238bceSAndroid Build Coastguard Worker const UVec3 m_numWorkGroups;
88*35238bceSAndroid Build Coastguard Worker
89*35238bceSAndroid Build Coastguard Worker uint32_t m_initialValue;
90*35238bceSAndroid Build Coastguard Worker
91*35238bceSAndroid Build Coastguard Worker private:
92*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase(const ShaderAtomicOpCase &other);
93*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase &operator=(const ShaderAtomicOpCase &other);
94*35238bceSAndroid Build Coastguard Worker
95*35238bceSAndroid Build Coastguard Worker ShaderProgram *m_program;
96*35238bceSAndroid Build Coastguard Worker };
97*35238bceSAndroid Build Coastguard Worker
ShaderAtomicOpCase(Context & context,const char * name,const char * funcName,AtomicOperandType operandType,DataType type,Precision precision,const UVec3 & workGroupSize)98*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase::ShaderAtomicOpCase(Context &context, const char *name, const char *funcName,
99*35238bceSAndroid Build Coastguard Worker AtomicOperandType operandType, DataType type, Precision precision,
100*35238bceSAndroid Build Coastguard Worker const UVec3 &workGroupSize)
101*35238bceSAndroid Build Coastguard Worker : TestCase(context, name, funcName)
102*35238bceSAndroid Build Coastguard Worker , m_funcName(funcName)
103*35238bceSAndroid Build Coastguard Worker , m_operandType(operandType)
104*35238bceSAndroid Build Coastguard Worker , m_type(type)
105*35238bceSAndroid Build Coastguard Worker , m_precision(precision)
106*35238bceSAndroid Build Coastguard Worker , m_workGroupSize(workGroupSize)
107*35238bceSAndroid Build Coastguard Worker , m_numWorkGroups(4, 4, 4)
108*35238bceSAndroid Build Coastguard Worker , m_initialValue(0)
109*35238bceSAndroid Build Coastguard Worker , m_program(DE_NULL)
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker }
112*35238bceSAndroid Build Coastguard Worker
~ShaderAtomicOpCase(void)113*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase::~ShaderAtomicOpCase(void)
114*35238bceSAndroid Build Coastguard Worker {
115*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase::deinit();
116*35238bceSAndroid Build Coastguard Worker }
117*35238bceSAndroid Build Coastguard Worker
init(void)118*35238bceSAndroid Build Coastguard Worker void ShaderAtomicOpCase::init(void)
119*35238bceSAndroid Build Coastguard Worker {
120*35238bceSAndroid Build Coastguard Worker const bool isSSBO = m_operandType == ATOMIC_OPERAND_BUFFER_VARIABLE;
121*35238bceSAndroid Build Coastguard Worker const char *precName = getPrecisionName(m_precision);
122*35238bceSAndroid Build Coastguard Worker const char *typeName = getDataTypeName(m_type);
123*35238bceSAndroid Build Coastguard Worker
124*35238bceSAndroid Build Coastguard Worker const DataType outType = isSSBO ? m_type : glu::TYPE_UINT;
125*35238bceSAndroid Build Coastguard Worker const char *outTypeName = getDataTypeName(outType);
126*35238bceSAndroid Build Coastguard Worker
127*35238bceSAndroid Build Coastguard Worker const uint32_t numValues = product(m_workGroupSize) * product(m_numWorkGroups);
128*35238bceSAndroid Build Coastguard Worker std::ostringstream src;
129*35238bceSAndroid Build Coastguard Worker
130*35238bceSAndroid Build Coastguard Worker src << glu::getGLSLVersionDeclaration(getContextTypeGLSLVersion(m_context.getRenderContext().getType())) << "\n"
131*35238bceSAndroid Build Coastguard Worker << "layout(local_size_x = " << m_workGroupSize.x() << ", local_size_y = " << m_workGroupSize.y()
132*35238bceSAndroid Build Coastguard Worker << ", local_size_z = " << m_workGroupSize.z() << ") in;\n"
133*35238bceSAndroid Build Coastguard Worker << "layout(binding = 0) buffer InOut\n"
134*35238bceSAndroid Build Coastguard Worker << "{\n"
135*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " inputValues[" << numValues << "];\n"
136*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << outTypeName << " outputValues[" << numValues << "];\n"
137*35238bceSAndroid Build Coastguard Worker << " " << (isSSBO ? "coherent " : "") << precName << " " << outTypeName << " groupValues["
138*35238bceSAndroid Build Coastguard Worker << product(m_numWorkGroups) << "];\n"
139*35238bceSAndroid Build Coastguard Worker << "} sb_inout;\n";
140*35238bceSAndroid Build Coastguard Worker
141*35238bceSAndroid Build Coastguard Worker if (!isSSBO)
142*35238bceSAndroid Build Coastguard Worker src << "shared " << precName << " " << typeName << " s_var;\n";
143*35238bceSAndroid Build Coastguard Worker
144*35238bceSAndroid Build Coastguard Worker src << "\n"
145*35238bceSAndroid Build Coastguard Worker << "void main (void)\n"
146*35238bceSAndroid Build Coastguard Worker << "{\n"
147*35238bceSAndroid Build Coastguard Worker << " uint localSize = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;\n"
148*35238bceSAndroid Build Coastguard Worker << " uint globalNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + "
149*35238bceSAndroid Build Coastguard Worker "gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
150*35238bceSAndroid Build Coastguard Worker << " uint globalOffs = localSize*globalNdx;\n"
151*35238bceSAndroid Build Coastguard Worker << " uint offset = globalOffs + gl_LocalInvocationIndex;\n"
152*35238bceSAndroid Build Coastguard Worker << "\n";
153*35238bceSAndroid Build Coastguard Worker
154*35238bceSAndroid Build Coastguard Worker if (isSSBO)
155*35238bceSAndroid Build Coastguard Worker {
156*35238bceSAndroid Build Coastguard Worker DE_ASSERT(outType == m_type);
157*35238bceSAndroid Build Coastguard Worker src << " sb_inout.outputValues[offset] = " << m_funcName
158*35238bceSAndroid Build Coastguard Worker << "(sb_inout.groupValues[globalNdx], sb_inout.inputValues[offset]);\n";
159*35238bceSAndroid Build Coastguard Worker }
160*35238bceSAndroid Build Coastguard Worker else
161*35238bceSAndroid Build Coastguard Worker {
162*35238bceSAndroid Build Coastguard Worker const string castBeg = outType != m_type ? (string(outTypeName) + "(") : string("");
163*35238bceSAndroid Build Coastguard Worker const char *const castEnd = outType != m_type ? ")" : "";
164*35238bceSAndroid Build Coastguard Worker
165*35238bceSAndroid Build Coastguard Worker src << " if (gl_LocalInvocationIndex == 0u)\n"
166*35238bceSAndroid Build Coastguard Worker << " s_var = " << typeName << "(" << tcu::toHex(m_initialValue) << "u);\n"
167*35238bceSAndroid Build Coastguard Worker << " barrier();\n"
168*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " res = " << m_funcName
169*35238bceSAndroid Build Coastguard Worker << "(s_var, sb_inout.inputValues[offset]);\n"
170*35238bceSAndroid Build Coastguard Worker << " sb_inout.outputValues[offset] = " << castBeg << "res" << castEnd << ";\n"
171*35238bceSAndroid Build Coastguard Worker << " barrier();\n"
172*35238bceSAndroid Build Coastguard Worker << " if (gl_LocalInvocationIndex == 0u)\n"
173*35238bceSAndroid Build Coastguard Worker << " sb_inout.groupValues[globalNdx] = " << castBeg << "s_var" << castEnd << ";\n";
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker
176*35238bceSAndroid Build Coastguard Worker src << "}\n";
177*35238bceSAndroid Build Coastguard Worker
178*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!m_program);
179*35238bceSAndroid Build Coastguard Worker m_program = new ShaderProgram(m_context.getRenderContext(), ProgramSources() << ComputeSource(src.str()));
180*35238bceSAndroid Build Coastguard Worker
181*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << *m_program;
182*35238bceSAndroid Build Coastguard Worker
183*35238bceSAndroid Build Coastguard Worker if (!m_program->isOk())
184*35238bceSAndroid Build Coastguard Worker {
185*35238bceSAndroid Build Coastguard Worker delete m_program;
186*35238bceSAndroid Build Coastguard Worker m_program = DE_NULL;
187*35238bceSAndroid Build Coastguard Worker throw tcu::TestError("Compile failed");
188*35238bceSAndroid Build Coastguard Worker }
189*35238bceSAndroid Build Coastguard Worker }
190*35238bceSAndroid Build Coastguard Worker
deinit(void)191*35238bceSAndroid Build Coastguard Worker void ShaderAtomicOpCase::deinit(void)
192*35238bceSAndroid Build Coastguard Worker {
193*35238bceSAndroid Build Coastguard Worker delete m_program;
194*35238bceSAndroid Build Coastguard Worker m_program = DE_NULL;
195*35238bceSAndroid Build Coastguard Worker }
196*35238bceSAndroid Build Coastguard Worker
iterate(void)197*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase::IterateResult ShaderAtomicOpCase::iterate(void)
198*35238bceSAndroid Build Coastguard Worker {
199*35238bceSAndroid Build Coastguard Worker const glw::Functions &gl = m_context.getRenderContext().getFunctions();
200*35238bceSAndroid Build Coastguard Worker const uint32_t program = m_program->getProgram();
201*35238bceSAndroid Build Coastguard Worker const Buffer inoutBuffer(m_context.getRenderContext());
202*35238bceSAndroid Build Coastguard Worker const uint32_t blockNdx = gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "InOut");
203*35238bceSAndroid Build Coastguard Worker const InterfaceBlockInfo blockInfo = getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, blockNdx);
204*35238bceSAndroid Build Coastguard Worker const uint32_t inVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.inputValues[0]");
205*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo inVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, inVarNdx);
206*35238bceSAndroid Build Coastguard Worker const uint32_t outVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.outputValues[0]");
207*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo outVarInfo =
208*35238bceSAndroid Build Coastguard Worker getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outVarNdx);
209*35238bceSAndroid Build Coastguard Worker const uint32_t groupVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.groupValues[0]");
210*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo groupVarInfo =
211*35238bceSAndroid Build Coastguard Worker getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, groupVarNdx);
212*35238bceSAndroid Build Coastguard Worker const uint32_t numValues = product(m_workGroupSize) * product(m_numWorkGroups);
213*35238bceSAndroid Build Coastguard Worker
214*35238bceSAndroid Build Coastguard Worker TCU_CHECK(inVarInfo.arraySize == numValues && outVarInfo.arraySize == numValues &&
215*35238bceSAndroid Build Coastguard Worker groupVarInfo.arraySize == product(m_numWorkGroups));
216*35238bceSAndroid Build Coastguard Worker
217*35238bceSAndroid Build Coastguard Worker gl.useProgram(program);
218*35238bceSAndroid Build Coastguard Worker
219*35238bceSAndroid Build Coastguard Worker // Setup buffer.
220*35238bceSAndroid Build Coastguard Worker {
221*35238bceSAndroid Build Coastguard Worker vector<uint8_t> bufData(blockInfo.dataSize);
222*35238bceSAndroid Build Coastguard Worker std::fill(bufData.begin(), bufData.end(), 0);
223*35238bceSAndroid Build Coastguard Worker
224*35238bceSAndroid Build Coastguard Worker getInputs((int)numValues, (int)inVarInfo.arrayStride, &bufData[0] + inVarInfo.offset);
225*35238bceSAndroid Build Coastguard Worker
226*35238bceSAndroid Build Coastguard Worker if (m_operandType == ATOMIC_OPERAND_BUFFER_VARIABLE)
227*35238bceSAndroid Build Coastguard Worker {
228*35238bceSAndroid Build Coastguard Worker for (uint32_t valNdx = 0; valNdx < product(m_numWorkGroups); valNdx++)
229*35238bceSAndroid Build Coastguard Worker *(uint32_t *)(&bufData[0] + groupVarInfo.offset + groupVarInfo.arrayStride * valNdx) = m_initialValue;
230*35238bceSAndroid Build Coastguard Worker }
231*35238bceSAndroid Build Coastguard Worker
232*35238bceSAndroid Build Coastguard Worker gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *inoutBuffer);
233*35238bceSAndroid Build Coastguard Worker gl.bufferData(GL_SHADER_STORAGE_BUFFER, blockInfo.dataSize, &bufData[0], GL_STATIC_READ);
234*35238bceSAndroid Build Coastguard Worker gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *inoutBuffer);
235*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed");
236*35238bceSAndroid Build Coastguard Worker }
237*35238bceSAndroid Build Coastguard Worker
238*35238bceSAndroid Build Coastguard Worker gl.dispatchCompute(m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
239*35238bceSAndroid Build Coastguard Worker
240*35238bceSAndroid Build Coastguard Worker // Read back and compare
241*35238bceSAndroid Build Coastguard Worker {
242*35238bceSAndroid Build Coastguard Worker const void *resPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, blockInfo.dataSize, GL_MAP_READ_BIT);
243*35238bceSAndroid Build Coastguard Worker bool isOk = true;
244*35238bceSAndroid Build Coastguard Worker
245*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
246*35238bceSAndroid Build Coastguard Worker TCU_CHECK(resPtr);
247*35238bceSAndroid Build Coastguard Worker
248*35238bceSAndroid Build Coastguard Worker isOk = verify((int)numValues, (int)inVarInfo.arrayStride, (const uint8_t *)resPtr + inVarInfo.offset,
249*35238bceSAndroid Build Coastguard Worker (int)outVarInfo.arrayStride, (const uint8_t *)resPtr + outVarInfo.offset,
250*35238bceSAndroid Build Coastguard Worker (int)groupVarInfo.arrayStride, (const uint8_t *)resPtr + groupVarInfo.offset);
251*35238bceSAndroid Build Coastguard Worker
252*35238bceSAndroid Build Coastguard Worker gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
253*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
254*35238bceSAndroid Build Coastguard Worker
255*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Comparison failed");
256*35238bceSAndroid Build Coastguard Worker }
257*35238bceSAndroid Build Coastguard Worker
258*35238bceSAndroid Build Coastguard Worker return STOP;
259*35238bceSAndroid Build Coastguard Worker }
260*35238bceSAndroid Build Coastguard Worker
261*35238bceSAndroid Build Coastguard Worker class ShaderAtomicAddCase : public ShaderAtomicOpCase
262*35238bceSAndroid Build Coastguard Worker {
263*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicAddCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)264*35238bceSAndroid Build Coastguard Worker ShaderAtomicAddCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
265*35238bceSAndroid Build Coastguard Worker Precision precision)
266*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicAdd", operandType, type, precision, UVec3(3, 2, 1))
267*35238bceSAndroid Build Coastguard Worker {
268*35238bceSAndroid Build Coastguard Worker m_initialValue = 1;
269*35238bceSAndroid Build Coastguard Worker }
270*35238bceSAndroid Build Coastguard Worker
271*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const272*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
273*35238bceSAndroid Build Coastguard Worker {
274*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
275*35238bceSAndroid Build Coastguard Worker const int maxVal = m_precision == PRECISION_LOWP ? 2 : 32;
276*35238bceSAndroid Build Coastguard Worker const int minVal = 1;
277*35238bceSAndroid Build Coastguard Worker
278*35238bceSAndroid Build Coastguard Worker // \todo [2013-09-04 pyry] Negative values!
279*35238bceSAndroid Build Coastguard Worker
280*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues; valNdx++)
281*35238bceSAndroid Build Coastguard Worker *(int *)((uint8_t *)inputs + stride * valNdx) = rnd.getInt(minVal, maxVal);
282*35238bceSAndroid Build Coastguard Worker }
283*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const284*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
285*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
286*35238bceSAndroid Build Coastguard Worker {
287*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
288*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
289*35238bceSAndroid Build Coastguard Worker
290*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
291*35238bceSAndroid Build Coastguard Worker {
292*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
293*35238bceSAndroid Build Coastguard Worker const int groupOutput = *(const int32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
294*35238bceSAndroid Build Coastguard Worker set<int> outValues;
295*35238bceSAndroid Build Coastguard Worker bool maxFound = false;
296*35238bceSAndroid Build Coastguard Worker int valueSum = (int)m_initialValue;
297*35238bceSAndroid Build Coastguard Worker
298*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
299*35238bceSAndroid Build Coastguard Worker {
300*35238bceSAndroid Build Coastguard Worker const int inputValue =
301*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
302*35238bceSAndroid Build Coastguard Worker valueSum += inputValue;
303*35238bceSAndroid Build Coastguard Worker }
304*35238bceSAndroid Build Coastguard Worker
305*35238bceSAndroid Build Coastguard Worker if (groupOutput != valueSum)
306*35238bceSAndroid Build Coastguard Worker {
307*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected sum "
308*35238bceSAndroid Build Coastguard Worker << valueSum << ", got " << groupOutput << TestLog::EndMessage;
309*35238bceSAndroid Build Coastguard Worker return false;
310*35238bceSAndroid Build Coastguard Worker }
311*35238bceSAndroid Build Coastguard Worker
312*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
313*35238bceSAndroid Build Coastguard Worker {
314*35238bceSAndroid Build Coastguard Worker const int inputValue =
315*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
316*35238bceSAndroid Build Coastguard Worker const int outputValue =
317*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
318*35238bceSAndroid Build Coastguard Worker
319*35238bceSAndroid Build Coastguard Worker if (!de::inRange(outputValue, (int)m_initialValue, valueSum - inputValue))
320*35238bceSAndroid Build Coastguard Worker {
321*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
322*35238bceSAndroid Build Coastguard Worker << localNdx << ": expected value in range [" << m_initialValue << ", "
323*35238bceSAndroid Build Coastguard Worker << (valueSum - inputValue) << "], got " << outputValue << TestLog::EndMessage;
324*35238bceSAndroid Build Coastguard Worker return false;
325*35238bceSAndroid Build Coastguard Worker }
326*35238bceSAndroid Build Coastguard Worker
327*35238bceSAndroid Build Coastguard Worker if (outValues.find(outputValue) != outValues.end())
328*35238bceSAndroid Build Coastguard Worker {
329*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
330*35238bceSAndroid Build Coastguard Worker << localNdx << ": found duplicate value " << outputValue << TestLog::EndMessage;
331*35238bceSAndroid Build Coastguard Worker return false;
332*35238bceSAndroid Build Coastguard Worker }
333*35238bceSAndroid Build Coastguard Worker
334*35238bceSAndroid Build Coastguard Worker outValues.insert(outputValue);
335*35238bceSAndroid Build Coastguard Worker if (outputValue == valueSum - inputValue)
336*35238bceSAndroid Build Coastguard Worker maxFound = true;
337*35238bceSAndroid Build Coastguard Worker }
338*35238bceSAndroid Build Coastguard Worker
339*35238bceSAndroid Build Coastguard Worker if (!maxFound)
340*35238bceSAndroid Build Coastguard Worker {
341*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: could not find maximum expected value from group "
342*35238bceSAndroid Build Coastguard Worker << groupNdx << TestLog::EndMessage;
343*35238bceSAndroid Build Coastguard Worker return false;
344*35238bceSAndroid Build Coastguard Worker }
345*35238bceSAndroid Build Coastguard Worker
346*35238bceSAndroid Build Coastguard Worker if (outValues.find((int)m_initialValue) == outValues.end())
347*35238bceSAndroid Build Coastguard Worker {
348*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: could not find initial value from group " << groupNdx
349*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
350*35238bceSAndroid Build Coastguard Worker return false;
351*35238bceSAndroid Build Coastguard Worker }
352*35238bceSAndroid Build Coastguard Worker }
353*35238bceSAndroid Build Coastguard Worker
354*35238bceSAndroid Build Coastguard Worker return true;
355*35238bceSAndroid Build Coastguard Worker }
356*35238bceSAndroid Build Coastguard Worker };
357*35238bceSAndroid Build Coastguard Worker
getPrecisionNumIntegerBits(glu::Precision precision)358*35238bceSAndroid Build Coastguard Worker static int getPrecisionNumIntegerBits(glu::Precision precision)
359*35238bceSAndroid Build Coastguard Worker {
360*35238bceSAndroid Build Coastguard Worker switch (precision)
361*35238bceSAndroid Build Coastguard Worker {
362*35238bceSAndroid Build Coastguard Worker case glu::PRECISION_HIGHP:
363*35238bceSAndroid Build Coastguard Worker return 32;
364*35238bceSAndroid Build Coastguard Worker case glu::PRECISION_MEDIUMP:
365*35238bceSAndroid Build Coastguard Worker return 16;
366*35238bceSAndroid Build Coastguard Worker case glu::PRECISION_LOWP:
367*35238bceSAndroid Build Coastguard Worker return 9;
368*35238bceSAndroid Build Coastguard Worker default:
369*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
370*35238bceSAndroid Build Coastguard Worker return 0;
371*35238bceSAndroid Build Coastguard Worker }
372*35238bceSAndroid Build Coastguard Worker }
373*35238bceSAndroid Build Coastguard Worker
getPrecisionMask(int numPreciseBits)374*35238bceSAndroid Build Coastguard Worker static uint32_t getPrecisionMask(int numPreciseBits)
375*35238bceSAndroid Build Coastguard Worker {
376*35238bceSAndroid Build Coastguard Worker // \note: bit shift with larger or equal than var length is undefined, use 64 bit ints
377*35238bceSAndroid Build Coastguard Worker return (uint32_t)((((uint64_t)1u) << numPreciseBits) - 1);
378*35238bceSAndroid Build Coastguard Worker }
379*35238bceSAndroid Build Coastguard Worker
intEqualsAfterUintCast(int32_t value,uint32_t casted,glu::Precision precision)380*35238bceSAndroid Build Coastguard Worker static bool intEqualsAfterUintCast(int32_t value, uint32_t casted, glu::Precision precision)
381*35238bceSAndroid Build Coastguard Worker {
382*35238bceSAndroid Build Coastguard Worker // Bit format of 'casted' = [ uint -> highp uint promotion bits (0) ] [ sign extend bits (s) ] [ value bits ]
383*35238bceSAndroid Build Coastguard Worker // |--min len---|
384*35238bceSAndroid Build Coastguard Worker // |---------------signed length---------|
385*35238bceSAndroid Build Coastguard Worker // |-------------------------------- highp uint length ----------------------------|
386*35238bceSAndroid Build Coastguard Worker
387*35238bceSAndroid Build Coastguard Worker const uint32_t reference = (uint32_t)value;
388*35238bceSAndroid Build Coastguard Worker const int signBitOn = value < 0;
389*35238bceSAndroid Build Coastguard Worker const int numPreciseBits = getPrecisionNumIntegerBits(precision);
390*35238bceSAndroid Build Coastguard Worker const uint32_t preciseMask = getPrecisionMask(numPreciseBits);
391*35238bceSAndroid Build Coastguard Worker
392*35238bceSAndroid Build Coastguard Worker // Lowest N bits must match, N = minimum precision
393*35238bceSAndroid Build Coastguard Worker if ((reference & preciseMask) != (casted & preciseMask))
394*35238bceSAndroid Build Coastguard Worker return false;
395*35238bceSAndroid Build Coastguard Worker
396*35238bceSAndroid Build Coastguard Worker // Other lowest bits must match the sign and the remaining (topmost) if any must be 0
397*35238bceSAndroid Build Coastguard Worker for (int signedIntegerLength = numPreciseBits; signedIntegerLength <= 32; ++signedIntegerLength)
398*35238bceSAndroid Build Coastguard Worker {
399*35238bceSAndroid Build Coastguard Worker const uint32_t signBits = (signBitOn) ? (getPrecisionMask(signedIntegerLength)) : (0u);
400*35238bceSAndroid Build Coastguard Worker
401*35238bceSAndroid Build Coastguard Worker if ((signBits & ~preciseMask) == (casted & ~preciseMask))
402*35238bceSAndroid Build Coastguard Worker return true;
403*35238bceSAndroid Build Coastguard Worker }
404*35238bceSAndroid Build Coastguard Worker return false;
405*35238bceSAndroid Build Coastguard Worker }
406*35238bceSAndroid Build Coastguard Worker
containsAfterUintCast(const std::set<int32_t> & haystack,uint32_t needle,glu::Precision precision)407*35238bceSAndroid Build Coastguard Worker static bool containsAfterUintCast(const std::set<int32_t> &haystack, uint32_t needle, glu::Precision precision)
408*35238bceSAndroid Build Coastguard Worker {
409*35238bceSAndroid Build Coastguard Worker for (std::set<int32_t>::const_iterator it = haystack.begin(); it != haystack.end(); ++it)
410*35238bceSAndroid Build Coastguard Worker if (intEqualsAfterUintCast(*it, needle, precision))
411*35238bceSAndroid Build Coastguard Worker return true;
412*35238bceSAndroid Build Coastguard Worker return false;
413*35238bceSAndroid Build Coastguard Worker }
414*35238bceSAndroid Build Coastguard Worker
containsAfterUintCast(const std::set<uint32_t> & haystack,int32_t needle,glu::Precision precision)415*35238bceSAndroid Build Coastguard Worker static bool containsAfterUintCast(const std::set<uint32_t> &haystack, int32_t needle, glu::Precision precision)
416*35238bceSAndroid Build Coastguard Worker {
417*35238bceSAndroid Build Coastguard Worker for (std::set<uint32_t>::const_iterator it = haystack.begin(); it != haystack.end(); ++it)
418*35238bceSAndroid Build Coastguard Worker if (intEqualsAfterUintCast(needle, *it, precision))
419*35238bceSAndroid Build Coastguard Worker return true;
420*35238bceSAndroid Build Coastguard Worker return false;
421*35238bceSAndroid Build Coastguard Worker }
422*35238bceSAndroid Build Coastguard Worker
423*35238bceSAndroid Build Coastguard Worker class ShaderAtomicMinCase : public ShaderAtomicOpCase
424*35238bceSAndroid Build Coastguard Worker {
425*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicMinCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)426*35238bceSAndroid Build Coastguard Worker ShaderAtomicMinCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
427*35238bceSAndroid Build Coastguard Worker Precision precision)
428*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicMin", operandType, type, precision, UVec3(3, 2, 1))
429*35238bceSAndroid Build Coastguard Worker {
430*35238bceSAndroid Build Coastguard Worker m_initialValue = m_precision == PRECISION_LOWP ? 100 : 1000;
431*35238bceSAndroid Build Coastguard Worker }
432*35238bceSAndroid Build Coastguard Worker
433*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const434*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
435*35238bceSAndroid Build Coastguard Worker {
436*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
437*35238bceSAndroid Build Coastguard Worker const bool isSigned = m_type == TYPE_INT;
438*35238bceSAndroid Build Coastguard Worker const int maxVal = m_precision == PRECISION_LOWP ? 100 : 1000;
439*35238bceSAndroid Build Coastguard Worker const int minVal = isSigned ? -maxVal : 0;
440*35238bceSAndroid Build Coastguard Worker
441*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues; valNdx++)
442*35238bceSAndroid Build Coastguard Worker *(int *)((uint8_t *)inputs + stride * valNdx) = rnd.getInt(minVal, maxVal);
443*35238bceSAndroid Build Coastguard Worker }
444*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const445*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
446*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
447*35238bceSAndroid Build Coastguard Worker {
448*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
449*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
450*35238bceSAndroid Build Coastguard Worker bool anyError = false;
451*35238bceSAndroid Build Coastguard Worker
452*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
453*35238bceSAndroid Build Coastguard Worker {
454*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
455*35238bceSAndroid Build Coastguard Worker const uint32_t groupOutput = *(const uint32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
456*35238bceSAndroid Build Coastguard Worker set<int32_t> inValues;
457*35238bceSAndroid Build Coastguard Worker set<uint32_t> outValues;
458*35238bceSAndroid Build Coastguard Worker int minValue = (int)m_initialValue;
459*35238bceSAndroid Build Coastguard Worker
460*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
461*35238bceSAndroid Build Coastguard Worker {
462*35238bceSAndroid Build Coastguard Worker const int32_t inputValue =
463*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
464*35238bceSAndroid Build Coastguard Worker inValues.insert(inputValue);
465*35238bceSAndroid Build Coastguard Worker minValue = de::min(inputValue, minValue);
466*35238bceSAndroid Build Coastguard Worker }
467*35238bceSAndroid Build Coastguard Worker
468*35238bceSAndroid Build Coastguard Worker if (!intEqualsAfterUintCast(minValue, groupOutput, m_precision))
469*35238bceSAndroid Build Coastguard Worker {
470*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected minimum "
471*35238bceSAndroid Build Coastguard Worker << minValue << " (" << tcu::Format::Hex<8>((uint32_t)minValue) << ")"
472*35238bceSAndroid Build Coastguard Worker << ", got " << groupOutput << " (" << tcu::Format::Hex<8>(groupOutput) << ")"
473*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
474*35238bceSAndroid Build Coastguard Worker anyError = true;
475*35238bceSAndroid Build Coastguard Worker }
476*35238bceSAndroid Build Coastguard Worker
477*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
478*35238bceSAndroid Build Coastguard Worker {
479*35238bceSAndroid Build Coastguard Worker const uint32_t outputValue =
480*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
481*35238bceSAndroid Build Coastguard Worker
482*35238bceSAndroid Build Coastguard Worker if (!containsAfterUintCast(inValues, outputValue, m_precision) &&
483*35238bceSAndroid Build Coastguard Worker !intEqualsAfterUintCast((int32_t)m_initialValue, outputValue, m_precision))
484*35238bceSAndroid Build Coastguard Worker {
485*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
486*35238bceSAndroid Build Coastguard Worker << localNdx << ": found unexpected value " << outputValue << " ("
487*35238bceSAndroid Build Coastguard Worker << tcu::Format::Hex<8>(outputValue) << ")" << TestLog::EndMessage;
488*35238bceSAndroid Build Coastguard Worker anyError = true;
489*35238bceSAndroid Build Coastguard Worker }
490*35238bceSAndroid Build Coastguard Worker
491*35238bceSAndroid Build Coastguard Worker outValues.insert(outputValue);
492*35238bceSAndroid Build Coastguard Worker }
493*35238bceSAndroid Build Coastguard Worker
494*35238bceSAndroid Build Coastguard Worker if (!containsAfterUintCast(outValues, (int)m_initialValue, m_precision))
495*35238bceSAndroid Build Coastguard Worker {
496*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: could not find initial value from group " << groupNdx
497*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
498*35238bceSAndroid Build Coastguard Worker anyError = true;
499*35238bceSAndroid Build Coastguard Worker }
500*35238bceSAndroid Build Coastguard Worker }
501*35238bceSAndroid Build Coastguard Worker
502*35238bceSAndroid Build Coastguard Worker return !anyError;
503*35238bceSAndroid Build Coastguard Worker }
504*35238bceSAndroid Build Coastguard Worker };
505*35238bceSAndroid Build Coastguard Worker
506*35238bceSAndroid Build Coastguard Worker class ShaderAtomicMaxCase : public ShaderAtomicOpCase
507*35238bceSAndroid Build Coastguard Worker {
508*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicMaxCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)509*35238bceSAndroid Build Coastguard Worker ShaderAtomicMaxCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
510*35238bceSAndroid Build Coastguard Worker Precision precision)
511*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicMax", operandType, type, precision, UVec3(3, 2, 1))
512*35238bceSAndroid Build Coastguard Worker {
513*35238bceSAndroid Build Coastguard Worker const bool isSigned = m_type == TYPE_INT;
514*35238bceSAndroid Build Coastguard Worker m_initialValue = isSigned ? (m_precision == PRECISION_LOWP ? -100 : -1000) : 0;
515*35238bceSAndroid Build Coastguard Worker }
516*35238bceSAndroid Build Coastguard Worker
517*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const518*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
519*35238bceSAndroid Build Coastguard Worker {
520*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
521*35238bceSAndroid Build Coastguard Worker const bool isSigned = m_type == TYPE_INT;
522*35238bceSAndroid Build Coastguard Worker const int maxVal = m_precision == PRECISION_LOWP ? 100 : 1000;
523*35238bceSAndroid Build Coastguard Worker const int minVal = isSigned ? -maxVal : 0;
524*35238bceSAndroid Build Coastguard Worker
525*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues; valNdx++)
526*35238bceSAndroid Build Coastguard Worker *(int *)((uint8_t *)inputs + stride * valNdx) = rnd.getInt(minVal, maxVal);
527*35238bceSAndroid Build Coastguard Worker }
528*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const529*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
530*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
531*35238bceSAndroid Build Coastguard Worker {
532*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
533*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
534*35238bceSAndroid Build Coastguard Worker bool anyError = false;
535*35238bceSAndroid Build Coastguard Worker
536*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
537*35238bceSAndroid Build Coastguard Worker {
538*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
539*35238bceSAndroid Build Coastguard Worker const uint32_t groupOutput = *(const uint32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
540*35238bceSAndroid Build Coastguard Worker set<int> inValues;
541*35238bceSAndroid Build Coastguard Worker set<uint32_t> outValues;
542*35238bceSAndroid Build Coastguard Worker int maxValue = (int)m_initialValue;
543*35238bceSAndroid Build Coastguard Worker
544*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
545*35238bceSAndroid Build Coastguard Worker {
546*35238bceSAndroid Build Coastguard Worker const int32_t inputValue =
547*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
548*35238bceSAndroid Build Coastguard Worker inValues.insert(inputValue);
549*35238bceSAndroid Build Coastguard Worker maxValue = de::max(maxValue, inputValue);
550*35238bceSAndroid Build Coastguard Worker }
551*35238bceSAndroid Build Coastguard Worker
552*35238bceSAndroid Build Coastguard Worker if (!intEqualsAfterUintCast(maxValue, groupOutput, m_precision))
553*35238bceSAndroid Build Coastguard Worker {
554*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected maximum "
555*35238bceSAndroid Build Coastguard Worker << maxValue << " (" << tcu::Format::Hex<8>((uint32_t)maxValue) << ")"
556*35238bceSAndroid Build Coastguard Worker << ", got " << groupOutput << " (" << tcu::Format::Hex<8>(groupOutput) << ")"
557*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
558*35238bceSAndroid Build Coastguard Worker anyError = true;
559*35238bceSAndroid Build Coastguard Worker }
560*35238bceSAndroid Build Coastguard Worker
561*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
562*35238bceSAndroid Build Coastguard Worker {
563*35238bceSAndroid Build Coastguard Worker const uint32_t outputValue =
564*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
565*35238bceSAndroid Build Coastguard Worker
566*35238bceSAndroid Build Coastguard Worker if (!containsAfterUintCast(inValues, outputValue, m_precision) &&
567*35238bceSAndroid Build Coastguard Worker !intEqualsAfterUintCast((int32_t)m_initialValue, outputValue, m_precision))
568*35238bceSAndroid Build Coastguard Worker {
569*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
570*35238bceSAndroid Build Coastguard Worker << localNdx << ": found unexpected value " << outputValue << " ("
571*35238bceSAndroid Build Coastguard Worker << tcu::Format::Hex<8>(outputValue) << ")" << TestLog::EndMessage;
572*35238bceSAndroid Build Coastguard Worker anyError = true;
573*35238bceSAndroid Build Coastguard Worker }
574*35238bceSAndroid Build Coastguard Worker
575*35238bceSAndroid Build Coastguard Worker outValues.insert(outputValue);
576*35238bceSAndroid Build Coastguard Worker }
577*35238bceSAndroid Build Coastguard Worker
578*35238bceSAndroid Build Coastguard Worker if (!containsAfterUintCast(outValues, (int)m_initialValue, m_precision))
579*35238bceSAndroid Build Coastguard Worker {
580*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: could not find initial value from group " << groupNdx
581*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
582*35238bceSAndroid Build Coastguard Worker anyError = true;
583*35238bceSAndroid Build Coastguard Worker }
584*35238bceSAndroid Build Coastguard Worker }
585*35238bceSAndroid Build Coastguard Worker
586*35238bceSAndroid Build Coastguard Worker return !anyError;
587*35238bceSAndroid Build Coastguard Worker }
588*35238bceSAndroid Build Coastguard Worker };
589*35238bceSAndroid Build Coastguard Worker
590*35238bceSAndroid Build Coastguard Worker class ShaderAtomicAndCase : public ShaderAtomicOpCase
591*35238bceSAndroid Build Coastguard Worker {
592*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicAndCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)593*35238bceSAndroid Build Coastguard Worker ShaderAtomicAndCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
594*35238bceSAndroid Build Coastguard Worker Precision precision)
595*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicAnd", operandType, type, precision, UVec3(3, 2, 1))
596*35238bceSAndroid Build Coastguard Worker {
597*35238bceSAndroid Build Coastguard Worker const int numBits = m_precision == PRECISION_HIGHP ? 32 : m_precision == PRECISION_MEDIUMP ? 16 : 8;
598*35238bceSAndroid Build Coastguard Worker const uint32_t valueMask = numBits == 32 ? ~0u : (1u << numBits) - 1u;
599*35238bceSAndroid Build Coastguard Worker m_initialValue = ~((1u << (numBits - 1u)) | 1u) & valueMask; // All bits except lowest and highest set.
600*35238bceSAndroid Build Coastguard Worker }
601*35238bceSAndroid Build Coastguard Worker
602*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const603*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
604*35238bceSAndroid Build Coastguard Worker {
605*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
606*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
607*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
608*35238bceSAndroid Build Coastguard Worker const int numBits = m_precision == PRECISION_HIGHP ? 32 : m_precision == PRECISION_MEDIUMP ? 16 : 8;
609*35238bceSAndroid Build Coastguard Worker const uint32_t valueMask = numBits == 32 ? ~0u : (1u << numBits) - 1u;
610*35238bceSAndroid Build Coastguard Worker
611*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
612*35238bceSAndroid Build Coastguard Worker {
613*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
614*35238bceSAndroid Build Coastguard Worker const uint32_t groupMask = 1 << rnd.getInt(0, numBits - 2); // One bit is always set.
615*35238bceSAndroid Build Coastguard Worker
616*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
617*35238bceSAndroid Build Coastguard Worker *(uint32_t *)((uint8_t *)inputs + stride * (groupOffset + localNdx)) =
618*35238bceSAndroid Build Coastguard Worker (rnd.getUint32() & valueMask) | groupMask;
619*35238bceSAndroid Build Coastguard Worker }
620*35238bceSAndroid Build Coastguard Worker }
621*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const622*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
623*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
624*35238bceSAndroid Build Coastguard Worker {
625*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
626*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
627*35238bceSAndroid Build Coastguard Worker const int numBits = m_precision == PRECISION_HIGHP ? 32 : m_precision == PRECISION_MEDIUMP ? 16 : 8;
628*35238bceSAndroid Build Coastguard Worker const uint32_t compareMask = (m_type == TYPE_UINT || numBits == 32) ? ~0u : (1u << numBits) - 1u;
629*35238bceSAndroid Build Coastguard Worker
630*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
631*35238bceSAndroid Build Coastguard Worker {
632*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
633*35238bceSAndroid Build Coastguard Worker const uint32_t groupOutput = *(const uint32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
634*35238bceSAndroid Build Coastguard Worker uint32_t expectedValue = m_initialValue;
635*35238bceSAndroid Build Coastguard Worker
636*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
637*35238bceSAndroid Build Coastguard Worker {
638*35238bceSAndroid Build Coastguard Worker const uint32_t inputValue =
639*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
640*35238bceSAndroid Build Coastguard Worker expectedValue &= inputValue;
641*35238bceSAndroid Build Coastguard Worker }
642*35238bceSAndroid Build Coastguard Worker
643*35238bceSAndroid Build Coastguard Worker if ((groupOutput & compareMask) != (expectedValue & compareMask))
644*35238bceSAndroid Build Coastguard Worker {
645*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected "
646*35238bceSAndroid Build Coastguard Worker << tcu::toHex(expectedValue) << ", got " << tcu::toHex(groupOutput)
647*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
648*35238bceSAndroid Build Coastguard Worker return false;
649*35238bceSAndroid Build Coastguard Worker }
650*35238bceSAndroid Build Coastguard Worker
651*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
652*35238bceSAndroid Build Coastguard Worker {
653*35238bceSAndroid Build Coastguard Worker const uint32_t outputValue =
654*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
655*35238bceSAndroid Build Coastguard Worker
656*35238bceSAndroid Build Coastguard Worker if ((compareMask & (outputValue & ~m_initialValue)) != 0)
657*35238bceSAndroid Build Coastguard Worker {
658*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
659*35238bceSAndroid Build Coastguard Worker << localNdx << ": found unexpected value " << tcu::toHex(outputValue)
660*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
661*35238bceSAndroid Build Coastguard Worker return false;
662*35238bceSAndroid Build Coastguard Worker }
663*35238bceSAndroid Build Coastguard Worker }
664*35238bceSAndroid Build Coastguard Worker }
665*35238bceSAndroid Build Coastguard Worker
666*35238bceSAndroid Build Coastguard Worker return true;
667*35238bceSAndroid Build Coastguard Worker }
668*35238bceSAndroid Build Coastguard Worker };
669*35238bceSAndroid Build Coastguard Worker
670*35238bceSAndroid Build Coastguard Worker class ShaderAtomicOrCase : public ShaderAtomicOpCase
671*35238bceSAndroid Build Coastguard Worker {
672*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicOrCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)673*35238bceSAndroid Build Coastguard Worker ShaderAtomicOrCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
674*35238bceSAndroid Build Coastguard Worker Precision precision)
675*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicOr", operandType, type, precision, UVec3(3, 2, 1))
676*35238bceSAndroid Build Coastguard Worker {
677*35238bceSAndroid Build Coastguard Worker m_initialValue = 1u; // Lowest bit set.
678*35238bceSAndroid Build Coastguard Worker }
679*35238bceSAndroid Build Coastguard Worker
680*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const681*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
682*35238bceSAndroid Build Coastguard Worker {
683*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
684*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
685*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
686*35238bceSAndroid Build Coastguard Worker const int numBits = m_precision == PRECISION_HIGHP ? 32 : m_precision == PRECISION_MEDIUMP ? 16 : 8;
687*35238bceSAndroid Build Coastguard Worker
688*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
689*35238bceSAndroid Build Coastguard Worker {
690*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
691*35238bceSAndroid Build Coastguard Worker
692*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
693*35238bceSAndroid Build Coastguard Worker *(uint32_t *)((uint8_t *)inputs + stride * (groupOffset + localNdx)) = 1u << rnd.getInt(0, numBits - 1);
694*35238bceSAndroid Build Coastguard Worker }
695*35238bceSAndroid Build Coastguard Worker }
696*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const697*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
698*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
699*35238bceSAndroid Build Coastguard Worker {
700*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
701*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
702*35238bceSAndroid Build Coastguard Worker const int numBits = m_precision == PRECISION_HIGHP ? 32 : m_precision == PRECISION_MEDIUMP ? 16 : 8;
703*35238bceSAndroid Build Coastguard Worker const uint32_t compareMask = (m_type == TYPE_UINT || numBits == 32) ? ~0u : (1u << numBits) - 1u;
704*35238bceSAndroid Build Coastguard Worker
705*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
706*35238bceSAndroid Build Coastguard Worker {
707*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
708*35238bceSAndroid Build Coastguard Worker const uint32_t groupOutput = *(const uint32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
709*35238bceSAndroid Build Coastguard Worker uint32_t expectedValue = m_initialValue;
710*35238bceSAndroid Build Coastguard Worker
711*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
712*35238bceSAndroid Build Coastguard Worker {
713*35238bceSAndroid Build Coastguard Worker const uint32_t inputValue =
714*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
715*35238bceSAndroid Build Coastguard Worker expectedValue |= inputValue;
716*35238bceSAndroid Build Coastguard Worker }
717*35238bceSAndroid Build Coastguard Worker
718*35238bceSAndroid Build Coastguard Worker if ((groupOutput & compareMask) != (expectedValue & compareMask))
719*35238bceSAndroid Build Coastguard Worker {
720*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected "
721*35238bceSAndroid Build Coastguard Worker << tcu::toHex(expectedValue) << ", got " << tcu::toHex(groupOutput)
722*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
723*35238bceSAndroid Build Coastguard Worker return false;
724*35238bceSAndroid Build Coastguard Worker }
725*35238bceSAndroid Build Coastguard Worker
726*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
727*35238bceSAndroid Build Coastguard Worker {
728*35238bceSAndroid Build Coastguard Worker const uint32_t outputValue =
729*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
730*35238bceSAndroid Build Coastguard Worker
731*35238bceSAndroid Build Coastguard Worker if ((compareMask & (outputValue & m_initialValue)) == 0)
732*35238bceSAndroid Build Coastguard Worker {
733*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
734*35238bceSAndroid Build Coastguard Worker << localNdx << ": found unexpected value " << tcu::toHex(outputValue)
735*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
736*35238bceSAndroid Build Coastguard Worker return false;
737*35238bceSAndroid Build Coastguard Worker }
738*35238bceSAndroid Build Coastguard Worker }
739*35238bceSAndroid Build Coastguard Worker }
740*35238bceSAndroid Build Coastguard Worker
741*35238bceSAndroid Build Coastguard Worker return true;
742*35238bceSAndroid Build Coastguard Worker }
743*35238bceSAndroid Build Coastguard Worker };
744*35238bceSAndroid Build Coastguard Worker
745*35238bceSAndroid Build Coastguard Worker class ShaderAtomicXorCase : public ShaderAtomicOpCase
746*35238bceSAndroid Build Coastguard Worker {
747*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicXorCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)748*35238bceSAndroid Build Coastguard Worker ShaderAtomicXorCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
749*35238bceSAndroid Build Coastguard Worker Precision precision)
750*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicXor", operandType, type, precision, UVec3(3, 2, 1))
751*35238bceSAndroid Build Coastguard Worker {
752*35238bceSAndroid Build Coastguard Worker m_initialValue = 0;
753*35238bceSAndroid Build Coastguard Worker }
754*35238bceSAndroid Build Coastguard Worker
755*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const756*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
757*35238bceSAndroid Build Coastguard Worker {
758*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
759*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
760*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
761*35238bceSAndroid Build Coastguard Worker
762*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
763*35238bceSAndroid Build Coastguard Worker {
764*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
765*35238bceSAndroid Build Coastguard Worker
766*35238bceSAndroid Build Coastguard Worker // First uses random bit-pattern.
767*35238bceSAndroid Build Coastguard Worker *(uint32_t *)((uint8_t *)inputs + stride * (groupOffset)) = rnd.getUint32();
768*35238bceSAndroid Build Coastguard Worker
769*35238bceSAndroid Build Coastguard Worker // Rest have either all or no bits set.
770*35238bceSAndroid Build Coastguard Worker for (int localNdx = 1; localNdx < workGroupSize; localNdx++)
771*35238bceSAndroid Build Coastguard Worker *(uint32_t *)((uint8_t *)inputs + stride * (groupOffset + localNdx)) = rnd.getBool() ? ~0u : 0u;
772*35238bceSAndroid Build Coastguard Worker }
773*35238bceSAndroid Build Coastguard Worker }
774*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const775*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
776*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
777*35238bceSAndroid Build Coastguard Worker {
778*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
779*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
780*35238bceSAndroid Build Coastguard Worker const int numBits = m_precision == PRECISION_HIGHP ? 32 : m_precision == PRECISION_MEDIUMP ? 16 : 8;
781*35238bceSAndroid Build Coastguard Worker const uint32_t compareMask = numBits == 32 ? ~0u : (1u << numBits) - 1u;
782*35238bceSAndroid Build Coastguard Worker
783*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
784*35238bceSAndroid Build Coastguard Worker {
785*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
786*35238bceSAndroid Build Coastguard Worker const uint32_t groupOutput = *(const uint32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
787*35238bceSAndroid Build Coastguard Worker const uint32_t randomValue = *(const int32_t *)((const uint8_t *)inputs + inputStride * groupOffset);
788*35238bceSAndroid Build Coastguard Worker const uint32_t expected0 = randomValue ^ 0u;
789*35238bceSAndroid Build Coastguard Worker const uint32_t expected1 = randomValue ^ ~0u;
790*35238bceSAndroid Build Coastguard Worker int numXorZeros = (m_initialValue == 0) ? 1 : 0;
791*35238bceSAndroid Build Coastguard Worker
792*35238bceSAndroid Build Coastguard Worker for (int localNdx = 1; localNdx < workGroupSize; localNdx++)
793*35238bceSAndroid Build Coastguard Worker {
794*35238bceSAndroid Build Coastguard Worker const uint32_t inputValue =
795*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)inputs + inputStride * (groupOffset + localNdx));
796*35238bceSAndroid Build Coastguard Worker if (inputValue == 0)
797*35238bceSAndroid Build Coastguard Worker numXorZeros += 1;
798*35238bceSAndroid Build Coastguard Worker }
799*35238bceSAndroid Build Coastguard Worker
800*35238bceSAndroid Build Coastguard Worker const uint32_t expected = (numXorZeros % 2 == 0) ? expected0 : expected1;
801*35238bceSAndroid Build Coastguard Worker
802*35238bceSAndroid Build Coastguard Worker if ((groupOutput & compareMask) != (expected & compareMask))
803*35238bceSAndroid Build Coastguard Worker {
804*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected "
805*35238bceSAndroid Build Coastguard Worker << tcu::toHex(expected0) << " or " << tcu::toHex(expected1) << " (compare mask "
806*35238bceSAndroid Build Coastguard Worker << tcu::toHex(compareMask) << "), got " << tcu::toHex(groupOutput)
807*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
808*35238bceSAndroid Build Coastguard Worker return false;
809*35238bceSAndroid Build Coastguard Worker }
810*35238bceSAndroid Build Coastguard Worker
811*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
812*35238bceSAndroid Build Coastguard Worker {
813*35238bceSAndroid Build Coastguard Worker const uint32_t outputValue =
814*35238bceSAndroid Build Coastguard Worker *(const uint32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
815*35238bceSAndroid Build Coastguard Worker
816*35238bceSAndroid Build Coastguard Worker if ((outputValue & compareMask) != 0 && (outputValue & compareMask) != compareMask &&
817*35238bceSAndroid Build Coastguard Worker (outputValue & compareMask) != (expected0 & compareMask) &&
818*35238bceSAndroid Build Coastguard Worker (outputValue & compareMask) != (expected1 & compareMask))
819*35238bceSAndroid Build Coastguard Worker {
820*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
821*35238bceSAndroid Build Coastguard Worker << localNdx << ": found unexpected value " << tcu::toHex(outputValue)
822*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
823*35238bceSAndroid Build Coastguard Worker return false;
824*35238bceSAndroid Build Coastguard Worker }
825*35238bceSAndroid Build Coastguard Worker }
826*35238bceSAndroid Build Coastguard Worker }
827*35238bceSAndroid Build Coastguard Worker
828*35238bceSAndroid Build Coastguard Worker return true;
829*35238bceSAndroid Build Coastguard Worker }
830*35238bceSAndroid Build Coastguard Worker };
831*35238bceSAndroid Build Coastguard Worker
832*35238bceSAndroid Build Coastguard Worker class ShaderAtomicExchangeCase : public ShaderAtomicOpCase
833*35238bceSAndroid Build Coastguard Worker {
834*35238bceSAndroid Build Coastguard Worker public:
ShaderAtomicExchangeCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)835*35238bceSAndroid Build Coastguard Worker ShaderAtomicExchangeCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
836*35238bceSAndroid Build Coastguard Worker Precision precision)
837*35238bceSAndroid Build Coastguard Worker : ShaderAtomicOpCase(context, name, "atomicExchange", operandType, type, precision, UVec3(3, 2, 1))
838*35238bceSAndroid Build Coastguard Worker {
839*35238bceSAndroid Build Coastguard Worker m_initialValue = 0;
840*35238bceSAndroid Build Coastguard Worker }
841*35238bceSAndroid Build Coastguard Worker
842*35238bceSAndroid Build Coastguard Worker protected:
getInputs(int numValues,int stride,void * inputs) const843*35238bceSAndroid Build Coastguard Worker void getInputs(int numValues, int stride, void *inputs) const
844*35238bceSAndroid Build Coastguard Worker {
845*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
846*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
847*35238bceSAndroid Build Coastguard Worker
848*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
849*35238bceSAndroid Build Coastguard Worker {
850*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
851*35238bceSAndroid Build Coastguard Worker
852*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
853*35238bceSAndroid Build Coastguard Worker *(int *)((uint8_t *)inputs + stride * (groupOffset + localNdx)) = localNdx + 1;
854*35238bceSAndroid Build Coastguard Worker }
855*35238bceSAndroid Build Coastguard Worker }
856*35238bceSAndroid Build Coastguard Worker
verify(int numValues,int inputStride,const void * inputs,int outputStride,const void * outputs,int groupStride,const void * groupOutputs) const857*35238bceSAndroid Build Coastguard Worker bool verify(int numValues, int inputStride, const void *inputs, int outputStride, const void *outputs,
858*35238bceSAndroid Build Coastguard Worker int groupStride, const void *groupOutputs) const
859*35238bceSAndroid Build Coastguard Worker {
860*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
861*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = numValues / workGroupSize;
862*35238bceSAndroid Build Coastguard Worker
863*35238bceSAndroid Build Coastguard Worker DE_UNREF(inputStride && inputs);
864*35238bceSAndroid Build Coastguard Worker
865*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
866*35238bceSAndroid Build Coastguard Worker {
867*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
868*35238bceSAndroid Build Coastguard Worker const int groupOutput = *(const int32_t *)((const uint8_t *)groupOutputs + groupNdx * groupStride);
869*35238bceSAndroid Build Coastguard Worker set<int> usedValues;
870*35238bceSAndroid Build Coastguard Worker
871*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
872*35238bceSAndroid Build Coastguard Worker {
873*35238bceSAndroid Build Coastguard Worker const int outputValue =
874*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)outputs + outputStride * (groupOffset + localNdx));
875*35238bceSAndroid Build Coastguard Worker
876*35238bceSAndroid Build Coastguard Worker if (!de::inRange(outputValue, 0, workGroupSize) || usedValues.find(outputValue) != usedValues.end())
877*35238bceSAndroid Build Coastguard Worker {
878*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
879*35238bceSAndroid Build Coastguard Worker << localNdx << ": found unexpected value " << outputValue << TestLog::EndMessage;
880*35238bceSAndroid Build Coastguard Worker return false;
881*35238bceSAndroid Build Coastguard Worker }
882*35238bceSAndroid Build Coastguard Worker usedValues.insert(outputValue);
883*35238bceSAndroid Build Coastguard Worker }
884*35238bceSAndroid Build Coastguard Worker
885*35238bceSAndroid Build Coastguard Worker if (!de::inRange(groupOutput, 0, workGroupSize) || usedValues.find(groupOutput) != usedValues.end())
886*35238bceSAndroid Build Coastguard Worker {
887*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": unexpected final value"
888*35238bceSAndroid Build Coastguard Worker << groupOutput << TestLog::EndMessage;
889*35238bceSAndroid Build Coastguard Worker return false;
890*35238bceSAndroid Build Coastguard Worker }
891*35238bceSAndroid Build Coastguard Worker }
892*35238bceSAndroid Build Coastguard Worker
893*35238bceSAndroid Build Coastguard Worker return true;
894*35238bceSAndroid Build Coastguard Worker }
895*35238bceSAndroid Build Coastguard Worker };
896*35238bceSAndroid Build Coastguard Worker
897*35238bceSAndroid Build Coastguard Worker class ShaderAtomicCompSwapCase : public TestCase
898*35238bceSAndroid Build Coastguard Worker {
899*35238bceSAndroid Build Coastguard Worker public:
900*35238bceSAndroid Build Coastguard Worker ShaderAtomicCompSwapCase(Context &context, const char *name, AtomicOperandType operandType, DataType type,
901*35238bceSAndroid Build Coastguard Worker Precision precision);
902*35238bceSAndroid Build Coastguard Worker ~ShaderAtomicCompSwapCase(void);
903*35238bceSAndroid Build Coastguard Worker
904*35238bceSAndroid Build Coastguard Worker void init(void);
905*35238bceSAndroid Build Coastguard Worker void deinit(void);
906*35238bceSAndroid Build Coastguard Worker IterateResult iterate(void);
907*35238bceSAndroid Build Coastguard Worker
908*35238bceSAndroid Build Coastguard Worker protected:
909*35238bceSAndroid Build Coastguard Worker private:
910*35238bceSAndroid Build Coastguard Worker ShaderAtomicCompSwapCase(const ShaderAtomicCompSwapCase &other);
911*35238bceSAndroid Build Coastguard Worker ShaderAtomicCompSwapCase &operator=(const ShaderAtomicCompSwapCase &other);
912*35238bceSAndroid Build Coastguard Worker
913*35238bceSAndroid Build Coastguard Worker const AtomicOperandType m_operandType;
914*35238bceSAndroid Build Coastguard Worker const DataType m_type;
915*35238bceSAndroid Build Coastguard Worker const Precision m_precision;
916*35238bceSAndroid Build Coastguard Worker
917*35238bceSAndroid Build Coastguard Worker const UVec3 m_workGroupSize;
918*35238bceSAndroid Build Coastguard Worker const UVec3 m_numWorkGroups;
919*35238bceSAndroid Build Coastguard Worker
920*35238bceSAndroid Build Coastguard Worker ShaderProgram *m_program;
921*35238bceSAndroid Build Coastguard Worker };
922*35238bceSAndroid Build Coastguard Worker
ShaderAtomicCompSwapCase(Context & context,const char * name,AtomicOperandType operandType,DataType type,Precision precision)923*35238bceSAndroid Build Coastguard Worker ShaderAtomicCompSwapCase::ShaderAtomicCompSwapCase(Context &context, const char *name, AtomicOperandType operandType,
924*35238bceSAndroid Build Coastguard Worker DataType type, Precision precision)
925*35238bceSAndroid Build Coastguard Worker : TestCase(context, name, "atomicCompSwap() Test")
926*35238bceSAndroid Build Coastguard Worker , m_operandType(operandType)
927*35238bceSAndroid Build Coastguard Worker , m_type(type)
928*35238bceSAndroid Build Coastguard Worker , m_precision(precision)
929*35238bceSAndroid Build Coastguard Worker , m_workGroupSize(3, 2, 1)
930*35238bceSAndroid Build Coastguard Worker , m_numWorkGroups(4, 4, 4)
931*35238bceSAndroid Build Coastguard Worker , m_program(DE_NULL)
932*35238bceSAndroid Build Coastguard Worker {
933*35238bceSAndroid Build Coastguard Worker }
934*35238bceSAndroid Build Coastguard Worker
~ShaderAtomicCompSwapCase(void)935*35238bceSAndroid Build Coastguard Worker ShaderAtomicCompSwapCase::~ShaderAtomicCompSwapCase(void)
936*35238bceSAndroid Build Coastguard Worker {
937*35238bceSAndroid Build Coastguard Worker ShaderAtomicCompSwapCase::deinit();
938*35238bceSAndroid Build Coastguard Worker }
939*35238bceSAndroid Build Coastguard Worker
init(void)940*35238bceSAndroid Build Coastguard Worker void ShaderAtomicCompSwapCase::init(void)
941*35238bceSAndroid Build Coastguard Worker {
942*35238bceSAndroid Build Coastguard Worker const bool isSSBO = m_operandType == ATOMIC_OPERAND_BUFFER_VARIABLE;
943*35238bceSAndroid Build Coastguard Worker const char *precName = getPrecisionName(m_precision);
944*35238bceSAndroid Build Coastguard Worker const char *typeName = getDataTypeName(m_type);
945*35238bceSAndroid Build Coastguard Worker const uint32_t numValues = product(m_workGroupSize) * product(m_numWorkGroups);
946*35238bceSAndroid Build Coastguard Worker std::ostringstream src;
947*35238bceSAndroid Build Coastguard Worker
948*35238bceSAndroid Build Coastguard Worker src << "#version 310 es\n"
949*35238bceSAndroid Build Coastguard Worker << "layout(local_size_x = " << m_workGroupSize.x() << ", local_size_y = " << m_workGroupSize.y()
950*35238bceSAndroid Build Coastguard Worker << ", local_size_z = " << m_workGroupSize.z() << ") in;\n"
951*35238bceSAndroid Build Coastguard Worker << "layout(binding = 0) buffer InOut\n"
952*35238bceSAndroid Build Coastguard Worker << "{\n"
953*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " compareValues[" << numValues << "];\n"
954*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " exchangeValues[" << numValues << "];\n"
955*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " outputValues[" << numValues << "];\n"
956*35238bceSAndroid Build Coastguard Worker << " " << (isSSBO ? "coherent " : "") << precName << " " << typeName << " groupValues["
957*35238bceSAndroid Build Coastguard Worker << product(m_numWorkGroups) << "];\n"
958*35238bceSAndroid Build Coastguard Worker << "} sb_inout;\n";
959*35238bceSAndroid Build Coastguard Worker
960*35238bceSAndroid Build Coastguard Worker if (!isSSBO)
961*35238bceSAndroid Build Coastguard Worker src << "shared " << precName << " " << typeName << " s_var;\n";
962*35238bceSAndroid Build Coastguard Worker
963*35238bceSAndroid Build Coastguard Worker src << "\n"
964*35238bceSAndroid Build Coastguard Worker << "void main (void)\n"
965*35238bceSAndroid Build Coastguard Worker << "{\n"
966*35238bceSAndroid Build Coastguard Worker << " uint localSize = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;\n"
967*35238bceSAndroid Build Coastguard Worker << " uint globalNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + "
968*35238bceSAndroid Build Coastguard Worker "gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
969*35238bceSAndroid Build Coastguard Worker << " uint globalOffs = localSize*globalNdx;\n"
970*35238bceSAndroid Build Coastguard Worker << " uint offset = globalOffs + gl_LocalInvocationIndex;\n"
971*35238bceSAndroid Build Coastguard Worker << "\n";
972*35238bceSAndroid Build Coastguard Worker
973*35238bceSAndroid Build Coastguard Worker if (!isSSBO)
974*35238bceSAndroid Build Coastguard Worker {
975*35238bceSAndroid Build Coastguard Worker src << " if (gl_LocalInvocationIndex == 0u)\n"
976*35238bceSAndroid Build Coastguard Worker << " s_var = " << typeName << "(" << 0 << ");\n"
977*35238bceSAndroid Build Coastguard Worker << "\n";
978*35238bceSAndroid Build Coastguard Worker }
979*35238bceSAndroid Build Coastguard Worker
980*35238bceSAndroid Build Coastguard Worker src << " " << precName << " " << typeName << " compare = sb_inout.compareValues[offset];\n"
981*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " exchange = sb_inout.exchangeValues[offset];\n"
982*35238bceSAndroid Build Coastguard Worker << " " << precName << " " << typeName << " result;\n"
983*35238bceSAndroid Build Coastguard Worker << " bool swapDone = false;\n"
984*35238bceSAndroid Build Coastguard Worker << "\n"
985*35238bceSAndroid Build Coastguard Worker << " for (uint ndx = 0u; ndx < localSize; ndx++)\n"
986*35238bceSAndroid Build Coastguard Worker << " {\n"
987*35238bceSAndroid Build Coastguard Worker << " barrier();\n"
988*35238bceSAndroid Build Coastguard Worker << " if (!swapDone)\n"
989*35238bceSAndroid Build Coastguard Worker << " {\n"
990*35238bceSAndroid Build Coastguard Worker << " result = atomicCompSwap(" << (isSSBO ? "sb_inout.groupValues[globalNdx]" : "s_var")
991*35238bceSAndroid Build Coastguard Worker << ", compare, exchange);\n"
992*35238bceSAndroid Build Coastguard Worker << " if (result == compare)\n"
993*35238bceSAndroid Build Coastguard Worker << " swapDone = true;\n"
994*35238bceSAndroid Build Coastguard Worker << " }\n"
995*35238bceSAndroid Build Coastguard Worker << " }\n"
996*35238bceSAndroid Build Coastguard Worker << "\n"
997*35238bceSAndroid Build Coastguard Worker << " sb_inout.outputValues[offset] = result;\n";
998*35238bceSAndroid Build Coastguard Worker
999*35238bceSAndroid Build Coastguard Worker if (!isSSBO)
1000*35238bceSAndroid Build Coastguard Worker {
1001*35238bceSAndroid Build Coastguard Worker src << " barrier();\n"
1002*35238bceSAndroid Build Coastguard Worker << " if (gl_LocalInvocationIndex == 0u)\n"
1003*35238bceSAndroid Build Coastguard Worker << " sb_inout.groupValues[globalNdx] = s_var;\n";
1004*35238bceSAndroid Build Coastguard Worker }
1005*35238bceSAndroid Build Coastguard Worker
1006*35238bceSAndroid Build Coastguard Worker src << "}\n";
1007*35238bceSAndroid Build Coastguard Worker
1008*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!m_program);
1009*35238bceSAndroid Build Coastguard Worker m_program = new ShaderProgram(m_context.getRenderContext(), ProgramSources() << ComputeSource(src.str()));
1010*35238bceSAndroid Build Coastguard Worker
1011*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << *m_program;
1012*35238bceSAndroid Build Coastguard Worker
1013*35238bceSAndroid Build Coastguard Worker if (!m_program->isOk())
1014*35238bceSAndroid Build Coastguard Worker {
1015*35238bceSAndroid Build Coastguard Worker delete m_program;
1016*35238bceSAndroid Build Coastguard Worker m_program = DE_NULL;
1017*35238bceSAndroid Build Coastguard Worker throw tcu::TestError("Compile failed");
1018*35238bceSAndroid Build Coastguard Worker }
1019*35238bceSAndroid Build Coastguard Worker }
1020*35238bceSAndroid Build Coastguard Worker
deinit(void)1021*35238bceSAndroid Build Coastguard Worker void ShaderAtomicCompSwapCase::deinit(void)
1022*35238bceSAndroid Build Coastguard Worker {
1023*35238bceSAndroid Build Coastguard Worker delete m_program;
1024*35238bceSAndroid Build Coastguard Worker m_program = DE_NULL;
1025*35238bceSAndroid Build Coastguard Worker }
1026*35238bceSAndroid Build Coastguard Worker
iterate(void)1027*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpCase::IterateResult ShaderAtomicCompSwapCase::iterate(void)
1028*35238bceSAndroid Build Coastguard Worker {
1029*35238bceSAndroid Build Coastguard Worker const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1030*35238bceSAndroid Build Coastguard Worker const uint32_t program = m_program->getProgram();
1031*35238bceSAndroid Build Coastguard Worker const Buffer inoutBuffer(m_context.getRenderContext());
1032*35238bceSAndroid Build Coastguard Worker const uint32_t blockNdx = gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "InOut");
1033*35238bceSAndroid Build Coastguard Worker const InterfaceBlockInfo blockInfo = getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, blockNdx);
1034*35238bceSAndroid Build Coastguard Worker const uint32_t cmpVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.compareValues[0]");
1035*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo cmpVarInfo =
1036*35238bceSAndroid Build Coastguard Worker getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, cmpVarNdx);
1037*35238bceSAndroid Build Coastguard Worker const uint32_t exhVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.exchangeValues[0]");
1038*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo exhVarInfo =
1039*35238bceSAndroid Build Coastguard Worker getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, exhVarNdx);
1040*35238bceSAndroid Build Coastguard Worker const uint32_t outVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.outputValues[0]");
1041*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo outVarInfo =
1042*35238bceSAndroid Build Coastguard Worker getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outVarNdx);
1043*35238bceSAndroid Build Coastguard Worker const uint32_t groupVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.groupValues[0]");
1044*35238bceSAndroid Build Coastguard Worker const InterfaceVariableInfo groupVarInfo =
1045*35238bceSAndroid Build Coastguard Worker getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, groupVarNdx);
1046*35238bceSAndroid Build Coastguard Worker const uint32_t numValues = product(m_workGroupSize) * product(m_numWorkGroups);
1047*35238bceSAndroid Build Coastguard Worker
1048*35238bceSAndroid Build Coastguard Worker TCU_CHECK(cmpVarInfo.arraySize == numValues && exhVarInfo.arraySize == numValues &&
1049*35238bceSAndroid Build Coastguard Worker outVarInfo.arraySize == numValues && groupVarInfo.arraySize == product(m_numWorkGroups));
1050*35238bceSAndroid Build Coastguard Worker
1051*35238bceSAndroid Build Coastguard Worker gl.useProgram(program);
1052*35238bceSAndroid Build Coastguard Worker
1053*35238bceSAndroid Build Coastguard Worker // \todo [2013-09-05 pyry] Use randomized input values!
1054*35238bceSAndroid Build Coastguard Worker
1055*35238bceSAndroid Build Coastguard Worker // Setup buffer.
1056*35238bceSAndroid Build Coastguard Worker {
1057*35238bceSAndroid Build Coastguard Worker const uint32_t workGroupSize = product(m_workGroupSize);
1058*35238bceSAndroid Build Coastguard Worker vector<uint8_t> bufData(blockInfo.dataSize);
1059*35238bceSAndroid Build Coastguard Worker
1060*35238bceSAndroid Build Coastguard Worker std::fill(bufData.begin(), bufData.end(), 0);
1061*35238bceSAndroid Build Coastguard Worker
1062*35238bceSAndroid Build Coastguard Worker for (uint32_t ndx = 0; ndx < numValues; ndx++)
1063*35238bceSAndroid Build Coastguard Worker *(uint32_t *)(&bufData[0] + cmpVarInfo.offset + cmpVarInfo.arrayStride * ndx) = ndx % workGroupSize;
1064*35238bceSAndroid Build Coastguard Worker
1065*35238bceSAndroid Build Coastguard Worker for (uint32_t ndx = 0; ndx < numValues; ndx++)
1066*35238bceSAndroid Build Coastguard Worker *(uint32_t *)(&bufData[0] + exhVarInfo.offset + exhVarInfo.arrayStride * ndx) = (ndx % workGroupSize) + 1;
1067*35238bceSAndroid Build Coastguard Worker
1068*35238bceSAndroid Build Coastguard Worker gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *inoutBuffer);
1069*35238bceSAndroid Build Coastguard Worker gl.bufferData(GL_SHADER_STORAGE_BUFFER, blockInfo.dataSize, &bufData[0], GL_STATIC_READ);
1070*35238bceSAndroid Build Coastguard Worker gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *inoutBuffer);
1071*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed");
1072*35238bceSAndroid Build Coastguard Worker }
1073*35238bceSAndroid Build Coastguard Worker
1074*35238bceSAndroid Build Coastguard Worker gl.dispatchCompute(m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
1075*35238bceSAndroid Build Coastguard Worker
1076*35238bceSAndroid Build Coastguard Worker // Read back and compare
1077*35238bceSAndroid Build Coastguard Worker {
1078*35238bceSAndroid Build Coastguard Worker const void *resPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, blockInfo.dataSize, GL_MAP_READ_BIT);
1079*35238bceSAndroid Build Coastguard Worker const int numWorkGroups = (int)product(m_numWorkGroups);
1080*35238bceSAndroid Build Coastguard Worker const int workGroupSize = (int)product(m_workGroupSize);
1081*35238bceSAndroid Build Coastguard Worker bool isOk = true;
1082*35238bceSAndroid Build Coastguard Worker
1083*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
1084*35238bceSAndroid Build Coastguard Worker TCU_CHECK(resPtr);
1085*35238bceSAndroid Build Coastguard Worker
1086*35238bceSAndroid Build Coastguard Worker for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++)
1087*35238bceSAndroid Build Coastguard Worker {
1088*35238bceSAndroid Build Coastguard Worker const int groupOffset = groupNdx * workGroupSize;
1089*35238bceSAndroid Build Coastguard Worker const int groupOutput =
1090*35238bceSAndroid Build Coastguard Worker *(const int32_t *)((const uint8_t *)resPtr + groupVarInfo.offset + groupNdx * groupVarInfo.arrayStride);
1091*35238bceSAndroid Build Coastguard Worker
1092*35238bceSAndroid Build Coastguard Worker for (int localNdx = 0; localNdx < workGroupSize; localNdx++)
1093*35238bceSAndroid Build Coastguard Worker {
1094*35238bceSAndroid Build Coastguard Worker const int refValue = localNdx;
1095*35238bceSAndroid Build Coastguard Worker const int outputValue = *(const int32_t *)((const uint8_t *)resPtr + outVarInfo.offset +
1096*35238bceSAndroid Build Coastguard Worker outVarInfo.arrayStride * (groupOffset + localNdx));
1097*35238bceSAndroid Build Coastguard Worker
1098*35238bceSAndroid Build Coastguard Worker if (outputValue != refValue)
1099*35238bceSAndroid Build Coastguard Worker {
1100*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation "
1101*35238bceSAndroid Build Coastguard Worker << localNdx << ": expected " << refValue << ", got " << outputValue
1102*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
1103*35238bceSAndroid Build Coastguard Worker isOk = false;
1104*35238bceSAndroid Build Coastguard Worker break;
1105*35238bceSAndroid Build Coastguard Worker }
1106*35238bceSAndroid Build Coastguard Worker }
1107*35238bceSAndroid Build Coastguard Worker
1108*35238bceSAndroid Build Coastguard Worker if (groupOutput != workGroupSize)
1109*35238bceSAndroid Build Coastguard Worker {
1110*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected"
1111*35238bceSAndroid Build Coastguard Worker << workGroupSize << ", got " << groupOutput << TestLog::EndMessage;
1112*35238bceSAndroid Build Coastguard Worker isOk = false;
1113*35238bceSAndroid Build Coastguard Worker break;
1114*35238bceSAndroid Build Coastguard Worker }
1115*35238bceSAndroid Build Coastguard Worker }
1116*35238bceSAndroid Build Coastguard Worker
1117*35238bceSAndroid Build Coastguard Worker gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
1118*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
1119*35238bceSAndroid Build Coastguard Worker
1120*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Comparison failed");
1121*35238bceSAndroid Build Coastguard Worker }
1122*35238bceSAndroid Build Coastguard Worker
1123*35238bceSAndroid Build Coastguard Worker return STOP;
1124*35238bceSAndroid Build Coastguard Worker }
1125*35238bceSAndroid Build Coastguard Worker
ShaderAtomicOpTests(Context & context,const char * name,AtomicOperandType operandType)1126*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpTests::ShaderAtomicOpTests(Context &context, const char *name, AtomicOperandType operandType)
1127*35238bceSAndroid Build Coastguard Worker : TestCaseGroup(context, name, "Atomic Operation Tests")
1128*35238bceSAndroid Build Coastguard Worker , m_operandType(operandType)
1129*35238bceSAndroid Build Coastguard Worker {
1130*35238bceSAndroid Build Coastguard Worker }
1131*35238bceSAndroid Build Coastguard Worker
~ShaderAtomicOpTests(void)1132*35238bceSAndroid Build Coastguard Worker ShaderAtomicOpTests::~ShaderAtomicOpTests(void)
1133*35238bceSAndroid Build Coastguard Worker {
1134*35238bceSAndroid Build Coastguard Worker }
1135*35238bceSAndroid Build Coastguard Worker
1136*35238bceSAndroid Build Coastguard Worker template <typename T>
createAtomicOpGroup(Context & context,AtomicOperandType operandType,const char * groupName)1137*35238bceSAndroid Build Coastguard Worker static tcu::TestCaseGroup *createAtomicOpGroup(Context &context, AtomicOperandType operandType, const char *groupName)
1138*35238bceSAndroid Build Coastguard Worker {
1139*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *const group =
1140*35238bceSAndroid Build Coastguard Worker new tcu::TestCaseGroup(context.getTestContext(), groupName, (string("Atomic ") + groupName).c_str());
1141*35238bceSAndroid Build Coastguard Worker try
1142*35238bceSAndroid Build Coastguard Worker {
1143*35238bceSAndroid Build Coastguard Worker for (int precNdx = 0; precNdx < PRECISION_LAST; precNdx++)
1144*35238bceSAndroid Build Coastguard Worker {
1145*35238bceSAndroid Build Coastguard Worker for (int typeNdx = 0; typeNdx < 2; typeNdx++)
1146*35238bceSAndroid Build Coastguard Worker {
1147*35238bceSAndroid Build Coastguard Worker const Precision precision = Precision(precNdx);
1148*35238bceSAndroid Build Coastguard Worker const DataType type = typeNdx > 0 ? TYPE_INT : TYPE_UINT;
1149*35238bceSAndroid Build Coastguard Worker const string caseName = string(getPrecisionName(precision)) + "_" + getDataTypeName(type);
1150*35238bceSAndroid Build Coastguard Worker
1151*35238bceSAndroid Build Coastguard Worker group->addChild(new T(context, caseName.c_str(), operandType, type, precision));
1152*35238bceSAndroid Build Coastguard Worker }
1153*35238bceSAndroid Build Coastguard Worker }
1154*35238bceSAndroid Build Coastguard Worker
1155*35238bceSAndroid Build Coastguard Worker return group;
1156*35238bceSAndroid Build Coastguard Worker }
1157*35238bceSAndroid Build Coastguard Worker catch (...)
1158*35238bceSAndroid Build Coastguard Worker {
1159*35238bceSAndroid Build Coastguard Worker delete group;
1160*35238bceSAndroid Build Coastguard Worker throw;
1161*35238bceSAndroid Build Coastguard Worker }
1162*35238bceSAndroid Build Coastguard Worker }
1163*35238bceSAndroid Build Coastguard Worker
init(void)1164*35238bceSAndroid Build Coastguard Worker void ShaderAtomicOpTests::init(void)
1165*35238bceSAndroid Build Coastguard Worker {
1166*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicAddCase>(m_context, m_operandType, "add"));
1167*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicMinCase>(m_context, m_operandType, "min"));
1168*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicMaxCase>(m_context, m_operandType, "max"));
1169*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicAndCase>(m_context, m_operandType, "and"));
1170*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicOrCase>(m_context, m_operandType, "or"));
1171*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicXorCase>(m_context, m_operandType, "xor"));
1172*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicExchangeCase>(m_context, m_operandType, "exchange"));
1173*35238bceSAndroid Build Coastguard Worker addChild(createAtomicOpGroup<ShaderAtomicCompSwapCase>(m_context, m_operandType, "compswap"));
1174*35238bceSAndroid Build Coastguard Worker }
1175*35238bceSAndroid Build Coastguard Worker
1176*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1177*35238bceSAndroid Build Coastguard Worker } // namespace gles31
1178*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1179