You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
863 lines
32 KiB
863 lines
32 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.1 Module
|
|
* -------------------------------------------------
|
|
*
|
|
* Copyright 2015 The Android Open Source Project
|
|
*
|
|
* 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
|
|
* \brief Program State Query tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es31fProgramStateQueryTests.hpp"
|
|
#include "es31fInfoLogQueryShared.hpp"
|
|
#include "glsStateQueryUtil.hpp"
|
|
#include "gluRenderContext.hpp"
|
|
#include "gluCallLogWrapper.hpp"
|
|
#include "gluContextInfo.hpp"
|
|
#include "gluObjectWrapper.hpp"
|
|
#include "gluShaderProgram.hpp"
|
|
#include "glwFunctions.hpp"
|
|
#include "glwEnums.hpp"
|
|
#include "tcuStringTemplate.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
|
|
using std::string;
|
|
using std::map;
|
|
|
|
namespace gles31
|
|
{
|
|
namespace Functional
|
|
{
|
|
namespace
|
|
{
|
|
|
|
using namespace gls::StateQueryUtil;
|
|
|
|
static const char* getVerifierSuffix (QueryType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case QUERY_PROGRAM_INTEGER_VEC3:
|
|
case QUERY_PROGRAM_INTEGER:
|
|
return "get_programiv";
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
return DE_NULL;
|
|
}
|
|
}
|
|
|
|
static std::string specializeShader(Context& context, const char* code)
|
|
{
|
|
const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(context.getRenderContext().getType());
|
|
std::map<std::string, std::string> specializationMap;
|
|
|
|
specializationMap["GLSL_VERSION_DECL"] = glu::getGLSLVersionDeclaration(glslVersion);
|
|
|
|
if (glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
|
|
{
|
|
specializationMap["GEOMETRY_SHADER_REQUIRE"] = "";
|
|
specializationMap["TESSELLATION_SHADER_REQUIRE"] = "";
|
|
}
|
|
else
|
|
{
|
|
specializationMap["GEOMETRY_SHADER_REQUIRE"] = "#extension GL_EXT_geometry_shader : require";
|
|
specializationMap["TESSELLATION_SHADER_REQUIRE"] = "#extension GL_EXT_tessellation_shader : require";
|
|
}
|
|
|
|
return tcu::StringTemplate(code).specialize(specializationMap);
|
|
}
|
|
|
|
|
|
class GeometryShaderCase : public TestCase
|
|
{
|
|
public:
|
|
GeometryShaderCase (Context& context, QueryType verifier, const char* name, const char* desc);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const QueryType m_verifier;
|
|
};
|
|
|
|
GeometryShaderCase::GeometryShaderCase (Context& context, QueryType verifier, const char* name, const char* desc)
|
|
: TestCase (context, name, desc)
|
|
, m_verifier (verifier)
|
|
{
|
|
}
|
|
|
|
GeometryShaderCase::IterateResult GeometryShaderCase::iterate (void)
|
|
{
|
|
const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
|
|
|
|
if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
|
|
TCU_THROW(NotSupportedError, "Geometry shader tests require GL_EXT_geometry_shader extension or an OpenGL ES 3.2 or higher context.");
|
|
|
|
|
|
static const char* const s_vtxFragTemplate = "${GLSL_VERSION_DECL}\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
static const char* const s_geometryTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"${GEOMETRY_SHADER_REQUIRE}\n"
|
|
"layout(triangles) in;"
|
|
"layout(triangle_strip, max_vertices = 3) out;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" EndPrimitive();\n"
|
|
"}\n";
|
|
|
|
static const char* const s_geometryTemplate2 = "${GLSL_VERSION_DECL}\n"
|
|
"${GEOMETRY_SHADER_REQUIRE}\n"
|
|
"layout(points) in;"
|
|
"layout(line_strip, max_vertices = 5) out;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" EndPrimitive();\n"
|
|
"}\n";
|
|
|
|
static const char* const s_geometryTemplate3 = "${GLSL_VERSION_DECL}\n"
|
|
"${GEOMETRY_SHADER_REQUIRE}\n"
|
|
"layout(points) in;"
|
|
"layout(points, max_vertices = 50) out;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" EndPrimitive();\n"
|
|
"}\n";
|
|
|
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
|
|
tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
|
|
|
|
gl.enableLogging(true);
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Layout", "triangles in, triangle strip out, 3 vertices");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::GeometrySource(specializeShader(m_context, s_geometryTemplate1)));
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "Compile failed");
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 3, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_TRIANGLES, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLE_STRIP, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_SHADER_INVOCATIONS, 1, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Layout", "points in, line strip out, 5 vertices");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::GeometrySource(specializeShader(m_context, s_geometryTemplate2)));
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "Compile failed");
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 5, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_POINTS, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_LINE_STRIP, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Layout", "points in, points out, 50 vertices");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::GeometrySource(specializeShader(m_context, s_geometryTemplate3)));
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "Compile failed");
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 50, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_POINTS, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_POINTS, m_verifier);
|
|
}
|
|
|
|
result.setTestContextResult(m_testCtx);
|
|
return STOP;
|
|
}
|
|
|
|
class TessellationShaderCase : public TestCase
|
|
{
|
|
public:
|
|
TessellationShaderCase (Context& context, QueryType verifier, const char* name, const char* desc);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const QueryType m_verifier;
|
|
};
|
|
|
|
TessellationShaderCase::TessellationShaderCase (Context& context, QueryType verifier, const char* name, const char* desc)
|
|
: TestCase (context, name, desc)
|
|
, m_verifier (verifier)
|
|
{
|
|
}
|
|
|
|
TessellationShaderCase::IterateResult TessellationShaderCase::iterate (void)
|
|
{
|
|
const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
|
|
|
|
if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
|
|
TCU_THROW(NotSupportedError, "Tessellation shader tests require GL_EXT_tessellation_shader extension or an OpenGL ES 3.2 or higher context.");
|
|
|
|
|
|
static const char* const s_vtxFragTemplate = "${GLSL_VERSION_DECL}\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
static const char* const s_tessCtrlTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(vertices = 3) out;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
static const char* const s_tessEvalTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(triangles, equal_spacing, cw) in;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
static const char* const s_tessCtrlTemplate2 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(vertices = 5) out;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
static const char* const s_tessEvalTemplate2 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(quads, fractional_even_spacing, ccw) in;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
static const char* const s_tessEvalTemplate3 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(isolines, fractional_odd_spacing, ccw, point_mode) in;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"}\n";
|
|
|
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
|
|
tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
|
|
|
|
gl.enableLogging(true);
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query State", "3 vertices, triangles, equal_spacing, cw");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate1))
|
|
<< glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate1)));
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "Compile failed");
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 3, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_TRIANGLES, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_EQUAL, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CW, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_FALSE, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query State", "5 vertices, quads, fractional_even_spacing, ccw");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate2))
|
|
<< glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate2)));
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "Compile failed");
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 5, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_QUADS, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_FRACTIONAL_EVEN, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CCW, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_FALSE, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query State", "5 vertices, isolines, fractional_odd_spacing, ccw, point_mode");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
|
|
<< glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate2))
|
|
<< glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate3)));
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "Compile failed");
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 5, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_ISOLINES, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_FRACTIONAL_ODD, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CCW, m_verifier);
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_TRUE, m_verifier);
|
|
}
|
|
|
|
result.setTestContextResult(m_testCtx);
|
|
return STOP;
|
|
}
|
|
|
|
class ProgramSeparableCase : public TestCase
|
|
{
|
|
public:
|
|
ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const QueryType m_verifier;
|
|
};
|
|
|
|
ProgramSeparableCase::ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc)
|
|
: TestCase (context, name, desc)
|
|
, m_verifier (verifier)
|
|
{
|
|
}
|
|
|
|
ProgramSeparableCase::IterateResult ProgramSeparableCase::iterate (void)
|
|
{
|
|
const string vtxTemplate = "${GLSL_VERSION_DECL}\n"
|
|
"out highp vec4 v_color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
|
|
" v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
|
|
"}\n";
|
|
const string fragTemplate = "${GLSL_VERSION_DECL}\n"
|
|
"in highp vec4 v_color;\n"
|
|
"layout(location=0) out highp vec4 o_color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" o_color = v_color;\n"
|
|
"}\n";
|
|
|
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
|
|
tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
|
|
glu::Shader vtxShader (m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
|
|
glu::Shader frgShader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
|
|
|
|
const std::string vStr = specializeShader(m_context, vtxTemplate.c_str());
|
|
const std::string fStr = specializeShader(m_context, fragTemplate.c_str());
|
|
const char* const vtxSourcePtr = vStr.c_str();
|
|
const char* const fragSourcePtr = fStr.c_str();
|
|
|
|
vtxShader.setSources(1, &vtxSourcePtr, DE_NULL);
|
|
frgShader.setSources(1, &fragSourcePtr, DE_NULL);
|
|
|
|
vtxShader.compile();
|
|
frgShader.compile();
|
|
|
|
{
|
|
const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxShader", "Vertex shader");
|
|
m_testCtx.getLog() << vtxShader;
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgShader", "Fragment shader");
|
|
m_testCtx.getLog() << frgShader;
|
|
}
|
|
|
|
TCU_CHECK_MSG(vtxShader.getCompileStatus() && frgShader.getCompileStatus(), "failed to build shaders");
|
|
|
|
gl.enableLogging(true);
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial");
|
|
glu::Program program (m_context.getRenderContext());
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetFalse", "SetFalse");
|
|
glu::Program program (m_context.getRenderContext());
|
|
int linkStatus = 0;
|
|
|
|
gl.glAttachShader(program.getProgram(), vtxShader.getShader());
|
|
gl.glAttachShader(program.getProgram(), frgShader.getShader());
|
|
gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
|
|
gl.glLinkProgram(program.getProgram());
|
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
|
|
|
|
gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
|
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
|
|
|
|
TCU_CHECK_MSG(linkStatus == GL_TRUE, "failed to link program");
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetTrue", "SetTrue");
|
|
glu::Program program (m_context.getRenderContext());
|
|
int linkStatus = 0;
|
|
|
|
gl.glAttachShader(program.getProgram(), vtxShader.getShader());
|
|
gl.glAttachShader(program.getProgram(), frgShader.getShader());
|
|
gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
|
|
gl.glLinkProgram(program.getProgram());
|
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
|
|
|
|
gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
|
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
|
|
|
|
TCU_CHECK_MSG(linkStatus == GL_TRUE, "failed to link program");
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE, m_verifier);
|
|
}
|
|
|
|
result.setTestContextResult(m_testCtx);
|
|
return STOP;
|
|
}
|
|
|
|
class ComputeWorkGroupSizeCase : public TestCase
|
|
{
|
|
public:
|
|
ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const QueryType m_verifier;
|
|
};
|
|
|
|
ComputeWorkGroupSizeCase::ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc)
|
|
: TestCase (context, name, desc)
|
|
, m_verifier (verifier)
|
|
{
|
|
}
|
|
|
|
ComputeWorkGroupSizeCase::IterateResult ComputeWorkGroupSizeCase::iterate (void)
|
|
{
|
|
static const char* const s_computeTemplate1D = "${GLSL_VERSION_DECL}\n"
|
|
"layout (local_size_x = 3) in;\n"
|
|
"layout(binding = 0) buffer Output\n"
|
|
"{\n"
|
|
" highp float val;\n"
|
|
"} sb_out;\n"
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" sb_out.val = 1.0;\n"
|
|
"}\n";
|
|
static const char* const s_computeTemplate2D = "${GLSL_VERSION_DECL}\n"
|
|
"layout (local_size_x = 3, local_size_y = 2) in;\n"
|
|
"layout(binding = 0) buffer Output\n"
|
|
"{\n"
|
|
" highp float val;\n"
|
|
"} sb_out;\n"
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" sb_out.val = 1.0;\n"
|
|
"}\n";
|
|
static const char* const s_computeTemplate3D = "${GLSL_VERSION_DECL}\n"
|
|
"layout (local_size_x = 3, local_size_y = 2, local_size_z = 4) in;\n"
|
|
"layout(binding = 0) buffer Output\n"
|
|
"{\n"
|
|
" highp float val;\n"
|
|
"} sb_out;\n"
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" sb_out.val = 1.0;\n"
|
|
"}\n";
|
|
|
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
|
|
tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
|
|
|
|
gl.enableLogging(true);
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "OneDimensional", "1D");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate1D)));
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "failed to build program");
|
|
|
|
verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 1, 1), m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "TwoDimensional", "2D");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate2D)));
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "failed to build program");
|
|
|
|
verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 1), m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "TreeDimensional", "3D");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate3D)));
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "failed to build program");
|
|
|
|
verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 4), m_verifier);
|
|
}
|
|
|
|
result.setTestContextResult(m_testCtx);
|
|
return STOP;
|
|
}
|
|
|
|
class ActiveAtomicCounterBuffersCase : public TestCase
|
|
{
|
|
public:
|
|
ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const QueryType m_verifier;
|
|
};
|
|
|
|
ActiveAtomicCounterBuffersCase::ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc)
|
|
: TestCase (context, name, desc)
|
|
, m_verifier (verifier)
|
|
{
|
|
}
|
|
|
|
ActiveAtomicCounterBuffersCase::IterateResult ActiveAtomicCounterBuffersCase::iterate (void)
|
|
{
|
|
static const char* const s_computeTemplate0 = "${GLSL_VERSION_DECL}\n"
|
|
"layout (local_size_x = 3) in;\n"
|
|
"layout(binding = 0) buffer Output\n"
|
|
"{\n"
|
|
" highp float val;\n"
|
|
"} sb_out;\n"
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" sb_out.val = 1.0;\n"
|
|
"}\n";
|
|
static const char* const s_computeTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"layout (local_size_x = 3) in;\n"
|
|
"layout(binding = 0) uniform highp atomic_uint u_counters[2];\n"
|
|
"layout(binding = 0) buffer Output\n"
|
|
"{\n"
|
|
" highp float val;\n"
|
|
"} sb_out;\n"
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" sb_out.val = float(atomicCounterIncrement(u_counters[0])) + float(atomicCounterIncrement(u_counters[1]));\n"
|
|
"}\n";
|
|
|
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
|
|
tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
|
|
|
|
gl.enableLogging(true);
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial");
|
|
glu::Program program (m_context.getRenderContext());
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "NoBuffers", "No buffers");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate0)));
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "failed to build program");
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
|
|
}
|
|
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "OneBuffer", "One buffer");
|
|
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate1)));
|
|
|
|
m_testCtx.getLog() << program;
|
|
|
|
TCU_CHECK_MSG(program.isOk(), "failed to build program");
|
|
|
|
verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 1, m_verifier);
|
|
}
|
|
|
|
result.setTestContextResult(m_testCtx);
|
|
return STOP;
|
|
}
|
|
|
|
class ProgramLogCase : public TestCase
|
|
{
|
|
public:
|
|
enum BuildErrorType
|
|
{
|
|
BUILDERROR_VERTEX_FRAGMENT = 0,
|
|
BUILDERROR_COMPUTE,
|
|
BUILDERROR_GEOMETRY,
|
|
BUILDERROR_TESSELLATION,
|
|
};
|
|
|
|
ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType);
|
|
|
|
private:
|
|
void init (void);
|
|
IterateResult iterate (void);
|
|
glu::ProgramSources getProgramSources (void) const;
|
|
|
|
const BuildErrorType m_buildErrorType;
|
|
};
|
|
|
|
ProgramLogCase::ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType)
|
|
: TestCase (ctx, name, desc)
|
|
, m_buildErrorType (errorType)
|
|
{
|
|
}
|
|
|
|
void ProgramLogCase::init (void)
|
|
{
|
|
const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
|
|
|
|
switch (m_buildErrorType)
|
|
{
|
|
case BUILDERROR_VERTEX_FRAGMENT:
|
|
case BUILDERROR_COMPUTE:
|
|
break;
|
|
|
|
case BUILDERROR_GEOMETRY:
|
|
if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
|
|
TCU_THROW(NotSupportedError, "Test requires GL_EXT_geometry_shader extension");
|
|
break;
|
|
|
|
case BUILDERROR_TESSELLATION:
|
|
if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
|
|
TCU_THROW(NotSupportedError, "Test requires GL_EXT_tessellation_shader extension");
|
|
break;
|
|
|
|
default:
|
|
DE_ASSERT(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ProgramLogCase::IterateResult ProgramLogCase::iterate (void)
|
|
{
|
|
using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
|
|
|
|
tcu::ResultCollector result (m_testCtx.getLog());
|
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
|
|
glu::ShaderProgram program (m_context.getRenderContext(), getProgramSources());
|
|
StateQueryMemoryWriteGuard<glw::GLint> logLen;
|
|
|
|
gl.enableLogging(true);
|
|
|
|
m_testCtx.getLog() << tcu::TestLog::Message << "Trying to link a broken program." << tcu::TestLog::EndMessage;
|
|
|
|
gl.glGetProgramiv(program.getProgram(), GL_INFO_LOG_LENGTH, &logLen);
|
|
logLen.verifyValidity(result);
|
|
|
|
if (logLen.verifyValidity(result))
|
|
verifyInfoLogQuery(result, gl, logLen, program.getProgram(), &glu::CallLogWrapper::glGetProgramInfoLog, "glGetProgramInfoLog");
|
|
|
|
result.setTestContextResult(m_testCtx);
|
|
return STOP;
|
|
}
|
|
|
|
glu::ProgramSources ProgramLogCase::getProgramSources (void) const
|
|
{
|
|
const char* const vertexTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"in highp vec4 a_pos;\n"
|
|
"uniform highp vec4 u_uniform;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = a_pos + u_uniform;\n"
|
|
"}\n";
|
|
const char* const vertexTemplate2 = "${GLSL_VERSION_DECL}\n"
|
|
"in highp vec4 a_pos;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = a_pos;\n"
|
|
"}\n";
|
|
const char* const fragmentTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"in highp vec4 v_missingVar;\n"
|
|
"uniform highp int u_uniform;\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" fragColor = v_missingVar + vec4(float(u_uniform));\n"
|
|
"}\n";
|
|
|
|
const char* const fragmentTemplate2 = "${GLSL_VERSION_DECL}\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" fragColor = vec4(1.0);\n"
|
|
"}\n";
|
|
const char* const computeTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"layout (binding = 0) buffer IOBuffer { highp float buf_var; };\n"
|
|
"uniform highp vec4 u_uniform;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" buf_var = u_uniform.x;\n"
|
|
"}\n";
|
|
const char* const geometryTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"${GEOMETRY_SHADER_REQUIRE}\n"
|
|
"layout(triangles) in;\n"
|
|
"layout(max_vertices=1, points) out;\n"
|
|
"in highp vec4 v_missingVar[];\n"
|
|
"uniform highp int u_uniform;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = gl_in[0].gl_Position + v_missingVar[2] + vec4(float(u_uniform));\n"
|
|
" EmitVertex();\n"
|
|
"}\n";
|
|
const char* const tessCtrlTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(vertices=2) out;"
|
|
"patch out highp vec2 vp_var;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position\n"
|
|
" gl_TessLevelOuter[0] = 0.8;\n"
|
|
" gl_TessLevelOuter[1] = 0.8;\n"
|
|
" if (gl_InvocationID == 0)\n"
|
|
" vp_var = gl_in[gl_InvocationID].gl_Position.xy;\n"
|
|
"}\n";
|
|
const char* const tessEvalTemplate1 = "${GLSL_VERSION_DECL}\n"
|
|
"${TESSELLATION_SHADER_REQUIRE}\n"
|
|
"layout(isolines) in;"
|
|
"in highp float vp_var[];\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(vp_var[1]);\n"
|
|
"}\n";
|
|
|
|
switch (m_buildErrorType)
|
|
{
|
|
case BUILDERROR_VERTEX_FRAGMENT:
|
|
return glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, vertexTemplate1))
|
|
<< glu::FragmentSource(specializeShader(m_context, fragmentTemplate1));
|
|
|
|
case BUILDERROR_COMPUTE:
|
|
return glu::ProgramSources()
|
|
<< glu::ComputeSource(specializeShader(m_context, computeTemplate1));
|
|
|
|
case BUILDERROR_GEOMETRY:
|
|
return glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, vertexTemplate1))
|
|
<< glu::GeometrySource(specializeShader(m_context, geometryTemplate1))
|
|
<< glu::FragmentSource(specializeShader(m_context, fragmentTemplate2));
|
|
|
|
case BUILDERROR_TESSELLATION:
|
|
return glu::ProgramSources()
|
|
<< glu::VertexSource(specializeShader(m_context, vertexTemplate2))
|
|
<< glu::TessellationControlSource(specializeShader(m_context, tessCtrlTemplate1))
|
|
<< glu::TessellationEvaluationSource(specializeShader(m_context, tessEvalTemplate1))
|
|
<< glu::FragmentSource(specializeShader(m_context, fragmentTemplate2));
|
|
|
|
default:
|
|
DE_ASSERT(false);
|
|
return glu::ProgramSources();
|
|
}
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
ProgramStateQueryTests::ProgramStateQueryTests (Context& context)
|
|
: TestCaseGroup(context, "program", "Program State Query tests")
|
|
{
|
|
}
|
|
|
|
ProgramStateQueryTests::~ProgramStateQueryTests (void)
|
|
{
|
|
}
|
|
|
|
void ProgramStateQueryTests::init (void)
|
|
{
|
|
static const QueryType intVerifiers[] =
|
|
{
|
|
QUERY_PROGRAM_INTEGER,
|
|
};
|
|
static const QueryType intVec3Verifiers[] =
|
|
{
|
|
QUERY_PROGRAM_INTEGER_VEC3,
|
|
};
|
|
|
|
#define FOR_EACH_INT_VERIFIER(X) \
|
|
for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVerifiers); ++verifierNdx) \
|
|
{ \
|
|
const char* verifierSuffix = getVerifierSuffix(intVerifiers[verifierNdx]); \
|
|
const QueryType verifier = intVerifiers[verifierNdx]; \
|
|
this->addChild(X); \
|
|
}
|
|
|
|
#define FOR_EACH_VEC_VERIFIER(X) \
|
|
for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVec3Verifiers); ++verifierNdx) \
|
|
{ \
|
|
const char* verifierSuffix = getVerifierSuffix(intVec3Verifiers[verifierNdx]); \
|
|
const QueryType verifier = intVec3Verifiers[verifierNdx]; \
|
|
this->addChild(X); \
|
|
}
|
|
|
|
FOR_EACH_INT_VERIFIER(new ProgramSeparableCase (m_context, verifier, (std::string("program_separable_") + verifierSuffix).c_str(), "Test PROGRAM_SEPARABLE"));
|
|
FOR_EACH_VEC_VERIFIER(new ComputeWorkGroupSizeCase (m_context, verifier, (std::string("compute_work_group_size_") + verifierSuffix).c_str(), "Test COMPUTE_WORK_GROUP_SIZE"));
|
|
FOR_EACH_INT_VERIFIER(new ActiveAtomicCounterBuffersCase (m_context, verifier, (std::string("active_atomic_counter_buffers_") + verifierSuffix).c_str(), "Test ACTIVE_ATOMIC_COUNTER_BUFFERS"));
|
|
FOR_EACH_INT_VERIFIER(new GeometryShaderCase (m_context, verifier, (std::string("geometry_shader_state_") + verifierSuffix).c_str(), "Test Geometry Shader State"));
|
|
FOR_EACH_INT_VERIFIER(new TessellationShaderCase (m_context, verifier, (std::string("tesselation_shader_state_") + verifierSuffix).c_str(), "Test Tesselation Shader State"));
|
|
|
|
#undef FOR_EACH_INT_VERIFIER
|
|
#undef FOR_EACH_VEC_VERIFIER
|
|
|
|
// program info log tests
|
|
// \note, there exists similar tests in gles3 module. However, the gles31 could use a different
|
|
// shader compiler with different INFO_LOG bugs.
|
|
{
|
|
static const struct
|
|
{
|
|
const char* caseName;
|
|
ProgramLogCase::BuildErrorType caseType;
|
|
} shaderTypes[] =
|
|
{
|
|
{ "info_log_vertex_fragment_link_fail", ProgramLogCase::BUILDERROR_VERTEX_FRAGMENT },
|
|
{ "info_log_compute_link_fail", ProgramLogCase::BUILDERROR_COMPUTE },
|
|
{ "info_log_geometry_link_fail", ProgramLogCase::BUILDERROR_GEOMETRY },
|
|
{ "info_log_tessellation_link_fail", ProgramLogCase::BUILDERROR_TESSELLATION },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
|
|
addChild(new ProgramLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType));
|
|
}
|
|
}
|
|
|
|
} // Functional
|
|
} // gles31
|
|
} // deqp
|