blob: 383eb2f97df43de82c6fe940b0b38965819d68be [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2017 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/ /*!
* \file gl4cShaderAtomicCounterOpsTests.cpp
* \brief Conformance tests for the ARB_shader_atomic_counter_ops functionality.
*/ /*-------------------------------------------------------------------*/
#include "gl4cShaderAtomicCounterOpsTests.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluDrawUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluShaderProgram.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuRenderTarget.hpp"
#include <algorithm>
#include <sstream>
#include <string>
using namespace glw;
namespace gl4cts
{
ShaderAtomicCounterOpsTestBase::ShaderPipeline::ShaderPipeline(glu::ShaderType testedShader, AtomicOperation* newOp,
bool contextGL46)
: m_program(NULL), m_programCompute(NULL), m_testedShader(testedShader), m_atomicOp(newOp)
{
m_shaders[glu::SHADERTYPE_VERTEX] = "<version>\n"
"<head>"
"in highp vec2 inPosition;\n"
"out highp vec3 vsPosition;\n"
"out highp vec4 vsColor;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(inPosition, 0.0, 1.0);\n"
" vsPosition = vec3(inPosition, 0.0);\n"
" vec4 outColor = vec4(1.0);\n"
"<atomic_operation>"
" vsColor = outColor;\n"
"}\n";
m_shaders[glu::SHADERTYPE_FRAGMENT] = "<version>\n"
"<head>"
"in highp vec4 gsColor;\n"
"out highp vec4 fsColor;\n"
"void main()\n"
"{\n"
" vec4 outColor = gsColor; \n"
"<atomic_operation>"
" fsColor = outColor;\n"
"}\n";
m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL] = "<version>\n"
"<head>"
"layout(vertices = 3) out;\n"
"in highp vec4 vsColor[];\n"
"in highp vec3 vsPosition[];\n"
"out highp vec3 tcsPosition[];\n"
"out highp vec4 tcsColor[];\n"
"void main()\n"
"{\n"
" tcsPosition[gl_InvocationID] = vsPosition[gl_InvocationID];\n"
" vec4 outColor = vsColor[gl_InvocationID];\n"
"<atomic_operation>"
" tcsColor[gl_InvocationID] = outColor;\n"
" gl_TessLevelInner[0] = 3;\n"
" gl_TessLevelOuter[0] = 3;\n"
" gl_TessLevelOuter[1] = 3;\n"
" gl_TessLevelOuter[2] = 3;\n"
"}\n";
m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION] = "<version>\n"
"<head>"
"layout(triangles, equal_spacing, cw) in;\n"
"in highp vec3 tcsPosition[];\n"
"in highp vec4 tcsColor[];\n"
"out highp vec4 tesColor;\n"
"void main()\n"
"{\n"
" vec3 p0 = gl_TessCoord.x * tcsPosition[0];\n"
" vec3 p1 = gl_TessCoord.y * tcsPosition[1];\n"
" vec3 p2 = gl_TessCoord.z * tcsPosition[2];\n"
" vec4 outColor = tcsColor[0];\n"
"<atomic_operation>"
" tesColor = outColor;\n"
" gl_Position = vec4(normalize(p0 + p1 + p2), 1.0);\n"
"}\n";
m_shaders[glu::SHADERTYPE_GEOMETRY] = "<version>\n"
"<head>"
"layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 3) out;\n"
"in highp vec4 tesColor[];\n"
"out highp vec4 gsColor;\n"
"void main()\n"
"{\n"
" for (int i = 0; i<3; i++)\n"
" {\n"
" gl_Position = gl_in[i].gl_Position;\n"
" vec4 outColor = tesColor[i];\n"
"<atomic_operation>"
" gsColor = outColor;\n"
" EmitVertex();\n"
" }\n"
" EndPrimitive();\n"
"}\n";
m_shaders[glu::SHADERTYPE_COMPUTE] = "<version>\n"
"<head>"
"layout(rgba32f, binding = 2) writeonly uniform highp image2D destImage;\n"
"layout (local_size_x = 16, local_size_y = 16) in;\n"
"void main (void)\n"
"{\n"
" vec4 outColor = vec4(1.0);\n"
"<atomic_operation>"
" imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n"
"}\n";
// prepare shaders
std::string postfix(contextGL46 ? "" : "ARB");
std::stringstream atomicOperationStream;
atomicOperationStream << "uint returned = " << m_atomicOp->getFunction() + postfix + "(counter, ";
if (m_atomicOp->getCompareValue() != 0)
{
atomicOperationStream << m_atomicOp->getCompareValue();
atomicOperationStream << "u, ";
}
atomicOperationStream << m_atomicOp->getParamValue();
atomicOperationStream << "u);\n";
atomicOperationStream << "uint after = atomicCounter(counter);\n";
if (m_atomicOp->shouldTestReturnValue())
{
atomicOperationStream << "if(after == returned) outColor = vec4(0.0f);\n";
}
atomicOperationStream << "atomicCounterIncrement(calls);\n";
std::string versionString;
std::string headString;
if (contextGL46)
{
versionString = "#version 460 core";
headString = "layout (binding=0) uniform atomic_uint counter;\n"
"layout (binding=1) uniform atomic_uint calls;\n";
}
else
{
versionString = "#version 450 core";
headString = "#extension GL_ARB_shader_atomic_counters: enable\n"
"#extension GL_ARB_shader_atomic_counter_ops: enable\n"
"layout (binding=0) uniform atomic_uint counter;\n"
"layout (binding=1) uniform atomic_uint calls;\n";
}
for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
{
prepareShader(m_shaders[i], "<version>", versionString);
prepareShader(m_shaders[i], "<head>", i == testedShader ? headString : "");
prepareShader(m_shaders[i], "<atomic_operation>", i == testedShader ? atomicOperationStream.str() : "");
}
}
ShaderAtomicCounterOpsTestBase::ShaderPipeline::~ShaderPipeline()
{
if (m_program)
{
delete m_program;
}
if (m_programCompute)
{
delete m_programCompute;
}
}
void ShaderAtomicCounterOpsTestBase::ShaderPipeline::prepareShader(std::string& shader, const std::string& tag,
const std::string& value)
{
size_t tagPos = shader.find(tag);
if (tagPos != std::string::npos)
shader.replace(tagPos, tag.length(), value);
}
void ShaderAtomicCounterOpsTestBase::ShaderPipeline::create(deqp::Context& context)
{
glu::ProgramSources sources;
for (unsigned int i = 0; i < glu::SHADERTYPE_COMPUTE; ++i)
{
if (!m_shaders[i].empty())
{
sources.sources[i].push_back(m_shaders[i]);
}
}
m_program = new glu::ShaderProgram(context.getRenderContext(), sources);
if (!m_program->isOk())
{
TCU_FAIL("Shader compilation failed");
}
glu::ProgramSources sourcesCompute;
sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(m_shaders[glu::SHADERTYPE_COMPUTE]);
m_programCompute = new glu::ShaderProgram(context.getRenderContext(), sourcesCompute);
if (!m_programCompute->isOk())
{
TCU_FAIL("Shader compilation failed");
}
}
void ShaderAtomicCounterOpsTestBase::ShaderPipeline::use(deqp::Context& context)
{
const glw::Functions& gl = context.getRenderContext().getFunctions();
gl.useProgram(m_program->getProgram());
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");
}
void ShaderAtomicCounterOpsTestBase::ShaderPipeline::test(deqp::Context& context)
{
const glw::Functions& gl = context.getRenderContext().getFunctions();
gl.clearColor(0.5f, 0.5f, 0.5f, 1.0f);
gl.clear(GL_COLOR_BUFFER_BIT);
if (m_testedShader == glu::SHADERTYPE_COMPUTE)
{
executeComputeShader(context);
}
else
{
renderQuad(context);
}
gl.flush();
}
void ShaderAtomicCounterOpsTestBase::ShaderPipeline::renderQuad(deqp::Context& context)
{
const glw::Functions& gl = context.getRenderContext().getFunctions();
deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, position) };
this->use(context);
glu::PrimitiveList primitiveList = glu::pr::Patches(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices);
glu::draw(context.getRenderContext(), this->getShaderProgram()->getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
vertexArrays, primitiveList);
GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier() error");
}
void ShaderAtomicCounterOpsTestBase::ShaderPipeline::executeComputeShader(deqp::Context& context)
{
const glw::Functions& gl = context.getRenderContext().getFunctions();
const glu::Texture outputTexture(context.getRenderContext());
gl.useProgram(m_programCompute->getProgram());
// output image
gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading image data failed");
// bind image
gl.bindImageTexture(2, *outputTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
GLU_EXPECT_NO_ERROR(gl.getError(), "Image setup failed");
// dispatch compute
gl.dispatchCompute(1, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() error");
gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier() error");
// render output texture
std::string vs = "#version 450 core\n"
"in highp vec2 position;\n"
"in vec2 inTexcoord;\n"
"out vec2 texcoord;\n"
"void main()\n"
"{\n"
" texcoord = inTexcoord;\n"
" gl_Position = vec4(position, 0.0, 1.0);\n"
"}\n";
std::string fs = "#version 450 core\n"
"uniform sampler2D sampler;\n"
"in vec2 texcoord;\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
" color = texture(sampler, texcoord);\n"
"}\n";
glu::ProgramSources sources;
sources.sources[glu::SHADERTYPE_VERTEX].push_back(vs);
sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fs);
glu::ShaderProgram renderShader(context.getRenderContext(), sources);
if (!m_program->isOk())
{
TCU_FAIL("Shader compilation failed");
}
gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri failed");
gl.useProgram(renderShader.getProgram());
GLU_EXPECT_NO_ERROR(gl.getError(), "useProgram failed");
gl.uniform1i(gl.getUniformLocation(renderShader.getProgram(), "sampler"), 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");
deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
float const texCoord[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("position", 2, 4, 0, position),
glu::va::Float("inTexcoord", 2, 4, 0, texCoord) };
glu::draw(context.getRenderContext(), renderShader.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
}
void ShaderAtomicCounterOpsTestBase::fillAtomicCounterBuffer(AtomicOperation* atomicOp)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLuint* dataPtr;
// fill values buffer
GLuint inputValue = atomicOp->getInputValue();
gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed.");
dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint),
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed.");
*dataPtr = inputValue;
gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed.");
// fill calls buffer
gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterCallsBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed.");
dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint),
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed.");
*dataPtr = 0;
gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed.");
}
bool ShaderAtomicCounterOpsTestBase::checkAtomicCounterBuffer(AtomicOperation* atomicOp)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLuint* dataPtr;
// get value
gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed.");
dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed.");
GLuint finalValue = *dataPtr;
gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed.");
// get calls
gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterCallsBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed.");
dataPtr = (GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange() call failed.");
GLuint numberOfCalls = *dataPtr;
gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer() call failed.");
// validate
GLuint expectedValue = atomicOp->getResult(numberOfCalls);
return finalValue == expectedValue;
}
void ShaderAtomicCounterOpsTestBase::bindBuffers()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_atomicCounterBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferBase() call failed.");
gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 1, m_atomicCounterCallsBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferBase() call failed.");
}
bool ShaderAtomicCounterOpsTestBase::validateColor(tcu::Vec4 testedColor, tcu::Vec4 desiredColor)
{
const float epsilon = 1.1f / 31.0f; // Accommodate framebuffers with 5-bit channels.
return de::abs(testedColor.x() - desiredColor.x()) < epsilon &&
de::abs(testedColor.y() - desiredColor.y()) < epsilon &&
de::abs(testedColor.z() - desiredColor.z()) < epsilon;
}
bool ShaderAtomicCounterOpsTestBase::validateScreenPixels(tcu::Vec4 desiredColor, tcu::Vec4 ignoredColor)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget();
tcu::IVec2 size(renderTarget.getWidth(), renderTarget.getHeight());
glw::GLfloat* pixels = new glw::GLfloat[size.x() * size.y() * 4];
// clear buffer
for (int x = 0; x < size.x(); ++x)
{
for (int y = 0; y < size.y(); ++y)
{
int mappedPixelPosition = y * size.x() + x;
pixels[mappedPixelPosition * 4 + 0] = -1.0f;
pixels[mappedPixelPosition * 4 + 1] = -1.0f;
pixels[mappedPixelPosition * 4 + 2] = -1.0f;
pixels[mappedPixelPosition * 4 + 3] = -1.0f;
}
}
// read pixels
gl.readPixels(0, 0, size.x(), size.y(), GL_RGBA, GL_FLOAT, pixels);
// validate pixels
bool rendered = false;
for (int x = 0; x < size.x(); ++x)
{
for (int y = 0; y < size.y(); ++y)
{
int mappedPixelPosition = y * size.x() + x;
tcu::Vec4 color(pixels[mappedPixelPosition * 4 + 0], pixels[mappedPixelPosition * 4 + 1],
pixels[mappedPixelPosition * 4 + 2], pixels[mappedPixelPosition * 4 + 3]);
if (!validateColor(color, ignoredColor))
{
rendered = true;
if (!validateColor(color, desiredColor))
{
delete[] pixels;
return false;
}
}
}
}
delete[] pixels;
return rendered;
}
ShaderAtomicCounterOpsTestBase::ShaderAtomicCounterOpsTestBase(deqp::Context& context, const char* name,
const char* description)
: TestCase(context, name, description), m_atomicCounterBuffer(0), m_atomicCounterCallsBuffer(0)
{
glu::ContextType contextType = m_context.getRenderContext().getType();
m_contextSupportsGL46 = glu::contextSupports(contextType, glu::ApiType::core(4, 6));
}
void ShaderAtomicCounterOpsTestBase::init()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
// generate atomic counter buffer
gl.genBuffers(1, &m_atomicCounterBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "genBuffers() call failed.");
gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed.");
gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData() call failed.");
// generate atomic counter calls buffer
gl.genBuffers(1, &m_atomicCounterCallsBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "genBuffers() call failed.");
gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_atomicCounterCallsBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer() call failed.");
gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData() call failed.");
// setup tested atomic operations
setOperations();
// setup shaders
for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
{
iter->create(m_context);
}
}
void ShaderAtomicCounterOpsTestBase::deinit()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
// delete atomic counter buffer
gl.deleteBuffers(1, &m_atomicCounterBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "deleteBuffers() call failed.");
// delete atomic counter calls buffer
gl.deleteBuffers(1, &m_atomicCounterCallsBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "deleteBuffers() call failed.");
// delete operations
for (AtomicOperationIter iter = m_operations.begin(); iter != m_operations.end(); ++iter)
{
delete *iter;
}
}
tcu::TestNode::IterateResult ShaderAtomicCounterOpsTestBase::iterate()
{
if (!m_contextSupportsGL46)
{
if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters") ||
!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counter_ops"))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
return STOP;
}
}
for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
{
fillAtomicCounterBuffer(iter->getAtomicOperation());
bindBuffers();
iter->test(m_context);
bool operationValueValid = checkAtomicCounterBuffer(iter->getAtomicOperation());
std::string operationFailMsg = "Result of atomic operation was different than expected (" +
iter->getAtomicOperation()->getFunction() + ").";
TCU_CHECK_MSG(operationValueValid, operationFailMsg.c_str());
bool returnValueValid = validateScreenPixels(tcu::Vec4(1.0f), tcu::Vec4(0.5f));
std::string returnFailMsg = "Result of atomic operation return value was different than expected (" +
iter->getAtomicOperation()->getFunction() + ").";
TCU_CHECK_MSG(returnValueValid, returnFailMsg.c_str());
}
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
return STOP;
}
/** Constructor.
*
* @param context Rendering context
*/
ShaderAtomicCounterOpsAdditionSubstractionTestCase::ShaderAtomicCounterOpsAdditionSubstractionTestCase(
deqp::Context& context)
: ShaderAtomicCounterOpsTestBase(
context, "ShaderAtomicCounterOpsAdditionSubstractionTestCase",
"Implements verification of new built-in addition and substraction atomic counter operations")
{
}
void ShaderAtomicCounterOpsAdditionSubstractionTestCase::setOperations()
{
glw::GLuint input = 12;
glw::GLuint param = 4;
addOperation(new AtomicOperationAdd(input, param));
addOperation(new AtomicOperationSubtract(input, param));
}
/** Constructor.
*
* @param context Rendering context
*/
ShaderAtomicCounterOpsMinMaxTestCase::ShaderAtomicCounterOpsMinMaxTestCase(deqp::Context& context)
: ShaderAtomicCounterOpsTestBase(
context, "ShaderAtomicCounterOpsMinMaxTestCase",
"Implements verification of new built-in minimum and maximum atomic counter operations")
{
}
void ShaderAtomicCounterOpsMinMaxTestCase::setOperations()
{
glw::GLuint input = 12;
glw::GLuint params[] = { 4, 16 };
addOperation(new AtomicOperationMin(input, params[0]));
addOperation(new AtomicOperationMin(input, params[1]));
addOperation(new AtomicOperationMax(input, params[0]));
addOperation(new AtomicOperationMax(input, params[1]));
}
/** Constructor.
*
* @param context Rendering context
*/
ShaderAtomicCounterOpsBitwiseTestCase::ShaderAtomicCounterOpsBitwiseTestCase(deqp::Context& context)
: ShaderAtomicCounterOpsTestBase(context, "ShaderAtomicCounterOpsBitwiseTestCase",
"Implements verification of new built-in bitwise atomic counter operations")
{
}
void ShaderAtomicCounterOpsBitwiseTestCase::setOperations()
{
glw::GLuint input = 0x2ED; // 0b1011101101;
glw::GLuint param = 0x3A9; // 0b1110101001;
addOperation(new AtomicOperationAnd(input, param));
addOperation(new AtomicOperationOr(input, param));
addOperation(new AtomicOperationXor(input, param));
}
/** Constructor.
*
* @param context Rendering context
*/
ShaderAtomicCounterOpsExchangeTestCase::ShaderAtomicCounterOpsExchangeTestCase(deqp::Context& context)
: ShaderAtomicCounterOpsTestBase(
context, "ShaderAtomicCounterOpsExchangeTestCase",
"Implements verification of new built-in exchange and swap atomic counter operations")
{
}
void ShaderAtomicCounterOpsExchangeTestCase::setOperations()
{
glw::GLuint input = 5;
glw::GLuint param = 10;
glw::GLuint compare[] = { 5, 20 };
addOperation(new AtomicOperationExchange(input, param));
addOperation(new AtomicOperationCompSwap(input, param, compare[0]));
addOperation(new AtomicOperationCompSwap(input, param, compare[1]));
}
/** Constructor.
*
* @param context Rendering context.
*/
ShaderAtomicCounterOps::ShaderAtomicCounterOps(deqp::Context& context)
: TestCaseGroup(context, "shader_atomic_counter_ops_tests",
"Verify conformance of CTS_ARB_shader_atomic_counter_ops implementation")
{
}
/** Initializes the test group contents. */
void ShaderAtomicCounterOps::init()
{
addChild(new ShaderAtomicCounterOpsAdditionSubstractionTestCase(m_context));
addChild(new ShaderAtomicCounterOpsMinMaxTestCase(m_context));
addChild(new ShaderAtomicCounterOpsBitwiseTestCase(m_context));
addChild(new ShaderAtomicCounterOpsExchangeTestCase(m_context));
}
} /* gl4cts namespace */