1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 * \file glcLimitTest.cpp
21 * \brief Definition of template class.
22 */ /*-------------------------------------------------------------------*/
26 template<typename DataType>
27 LimitCase<DataType>::LimitCase(deqp::Context& context,
30 DataType limitBoundry,
31 bool isBoundryMaximum,
32 const char* glslVersion,
33 const char* glslBuiltin,
34 const char* glslExtension)
35 : deqp::TestCase(context, caseName, "Token limit validation.")
36 , m_limitToken(limitToken)
37 , m_limitBoundry(limitBoundry)
38 , m_isBoundryMaximum(isBoundryMaximum)
39 , m_glslVersion(glslVersion)
40 , m_glslBuiltin(glslBuiltin)
41 , m_glslExtension(glslExtension)
45 template<typename DataType>
46 LimitCase<DataType>::~LimitCase(void)
50 template<typename DataType>
51 tcu::TestNode::IterateResult LimitCase<DataType>::iterate(void)
53 DataType limitValue = DataType();
54 const Functions& gl = m_context.getRenderContext().getFunctions();
56 // make sure that limit or builtin was specified
57 DE_ASSERT(m_limitToken || !m_glslBuiltin.empty());
59 // check if limit was specified
62 // check if limit is not smaller or greater then boundry defined in specification
63 limitValue = getLimitValue(gl);
64 if (!isWithinBoundry(limitValue))
66 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
70 // if glsl builtin wasn't defined then test already passed
71 if (m_glslBuiltin.empty())
73 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
78 // create compute shader to check glsl builtin
79 std::string shaderSource = createShader();
80 const GLchar* source = shaderSource.c_str();
81 const GLuint program = gl.createProgram();
82 GLuint shader = gl.createShader(GL_COMPUTE_SHADER);
83 gl.attachShader(program, shader);
84 gl.deleteShader(shader);
85 gl.shaderSource(shader, 1, &source, NULL);
86 gl.compileShader(shader);
87 gl.linkProgram(program);
90 gl.getProgramiv(program, GL_LINK_STATUS, &status);
92 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &length);
95 std::vector<GLchar> log(length);
96 gl.getProgramInfoLog(program, length, NULL, &log[0]);
97 m_testCtx.getLog() << tcu::TestLog::Message
99 << tcu::TestLog::EndMessage;
101 if (status == GL_FALSE)
103 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
107 gl.useProgram(program);
110 gl.genBuffers(1, &buffer);
111 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
112 gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(DataType), NULL, GL_DYNAMIC_DRAW);
113 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
115 gl.dispatchCompute(1, 1, 1);
117 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
118 gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
119 DataType* data = static_cast<DataType*>(gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(DataType), GL_MAP_READ_BIT));
120 DataType builtinValue = data[0];
121 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
122 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
126 // limit token was specified - compare builtin to it
127 if (isEqual(limitValue, builtinValue))
129 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
133 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
134 m_testCtx.getLog() << tcu::TestLog::Message
135 << "Shader builtin has value: "
137 << " which is different then the value of corresponding limit: "
139 << tcu::TestLog::EndMessage;
144 // limit token was not specified - compare builtin to the boundry
145 if (isWithinBoundry(builtinValue, true))
147 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
151 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
152 m_testCtx.getLog() << tcu::TestLog::Message
153 << "Shader builtin value is: "
155 << " which is outside of specified boundry."
156 << tcu::TestLog::EndMessage;
163 template<typename DataType>
164 bool LimitCase<DataType>::isWithinBoundry(DataType value, bool isBuiltin) const
166 if (m_isBoundryMaximum)
168 // value should be smaller or euqual to boundry
169 if (isGreater(value, m_limitBoundry))
171 m_testCtx.getLog() << tcu::TestLog::Message
172 << (isBuiltin ? "Builtin" : "Limit")
175 << " when it should not be greater than "
177 << tcu::TestLog::EndMessage;
183 // value should be greater or euqual to boundry
184 if (isSmaller(value, m_limitBoundry))
186 m_testCtx.getLog() << tcu::TestLog::Message
187 << (isBuiltin ? "Builtin" : "Limit")
190 << "when it should not be smaller than "
192 << tcu::TestLog::EndMessage;
200 template<typename DataType>
201 std::string LimitCase<DataType>::createShader() const
203 std::stringstream shader;
204 shader << "#version " << m_glslVersion << "\n";
205 if (!m_glslExtension.empty())
206 shader << "#extension " + m_glslExtension + " : require\n";
207 shader << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
208 "layout(std430) buffer Output {\n"
209 << getGLSLDataType() <<" data; } g_out;"
211 "g_out.data = " << m_glslBuiltin << "; }";
215 template<typename DataType>
216 std::string LimitCase<DataType>::getGLSLDataType() const
222 std::string LimitCase<GLfloat>::getGLSLDataType() const
228 std::string LimitCase<tcu::IVec3>::getGLSLDataType() const
233 template<typename DataType>
234 bool LimitCase<DataType>::isEqual(DataType a, DataType b) const
240 bool LimitCase<tcu::IVec3>::isEqual(tcu::IVec3 a, tcu::IVec3 b) const
242 tcu::BVec3 bVec = tcu::equal(a, b);
243 return tcu::boolAll(bVec);
246 template<typename DataType>
247 bool LimitCase<DataType>::isGreater(DataType a, DataType b) const
253 bool LimitCase<tcu::IVec3>::isGreater(tcu::IVec3 a, tcu::IVec3 b) const
255 tcu::BVec3 bVec = tcu::greaterThan(a, b);
256 return tcu::boolAll(bVec);
259 template<typename DataType>
260 bool LimitCase<DataType>::isSmaller(DataType a, DataType b) const
266 bool LimitCase<tcu::IVec3>::isSmaller(tcu::IVec3 a, tcu::IVec3 b) const
268 tcu::BVec3 bVec = tcu::lessThan(a, b);
269 return tcu::boolAll(bVec);
272 template<typename DataType>
273 DataType LimitCase<DataType>::getLimitValue(const Functions&) const
279 GLint LimitCase<GLint>::getLimitValue(const Functions& gl) const
282 gl.getIntegerv(m_limitToken, &value);
283 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
288 GLint64 LimitCase<GLint64>::getLimitValue(const Functions& gl) const
291 gl.getInteger64v(m_limitToken, &value);
292 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v");
297 GLuint64 LimitCase<GLuint64>::getLimitValue(const Functions& gl) const
300 gl.getInteger64v(m_limitToken, &value);
301 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v");
302 return static_cast<GLuint64>(value);
306 GLfloat LimitCase<GLfloat>::getLimitValue(const Functions& gl) const
309 gl.getFloatv(m_limitToken, &value);
310 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv");
315 tcu::IVec3 LimitCase<tcu::IVec3>::getLimitValue(const Functions& gl) const
317 tcu::IVec3 value(-1);
318 for (int i = 0; i < 3; i++)
319 gl.getIntegeri_v(m_limitToken, (GLuint)i, &value[i]);
320 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegeri_v");