/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.1 Module
* -------------------------------------------------
*
* Copyright 2014 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 Shader state query tests
*//*--------------------------------------------------------------------*/
#include "es31fShaderStateQueryTests.hpp"
#include "tcuTestLog.hpp"
#include "tcuStringTemplate.hpp"
#include "gluShaderProgram.hpp"
#include "gluRenderContext.hpp"
#include "gluContextInfo.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{
class SamplerTypeCase : public TestCase
{
public:
SamplerTypeCase (Context& ctx, const char* name, const char* desc);
private:
IterateResult iterate (void);
};
SamplerTypeCase::SamplerTypeCase (Context& ctx, const char* name, const char* desc)
: TestCase(ctx, name, desc)
{
}
SamplerTypeCase::IterateResult SamplerTypeCase::iterate (void)
{
static const struct SamplerType
{
glw::GLenum glType;
const char* typeStr;
const char* samplePosStr;
bool isArray;
} samplerTypes[] =
{
{ GL_SAMPLER_2D_MULTISAMPLE, "sampler2DMS", "ivec2(gl_FragCoord.xy)", false },
{ GL_INT_SAMPLER_2D_MULTISAMPLE, "isampler2DMS", "ivec2(gl_FragCoord.xy)", false },
{ GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, "usampler2DMS", "ivec2(gl_FragCoord.xy)", false },
{ GL_SAMPLER_2D_MULTISAMPLE_ARRAY, "sampler2DMSArray", "ivec3(gl_FragCoord.xyz)", true },
{ GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "isampler2DMSArray", "ivec3(gl_FragCoord.xyz)", true },
{ GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "usampler2DMSArray", "ivec3(gl_FragCoord.xyz)", true },
};
static const char* const vertexSource = "#version 310 es\n"
"in highp vec4 a_position;\n"
"void main(void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
static const char* const fragmentSourceTemplate = "#version 310 es\n"
"${EXTENSIONSTATEMENT}"
"uniform highp ${SAMPLERTYPE} u_sampler;\n"
"layout(location = 0) out highp vec4 dEQP_FragColor;\n"
"void main(void)\n"
"{\n"
" dEQP_FragColor = vec4(texelFetch(u_sampler, ${POSITION}, 0));\n"
"}\n";
const bool textureArraySupported = m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
bool error = false;
for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(samplerTypes); ++typeNdx)
{
const tcu::ScopedLogSection section(m_testCtx.getLog(), std::string(samplerTypes[typeNdx].typeStr), std::string() + "Sampler type " + samplerTypes[typeNdx].typeStr);
if (samplerTypes[typeNdx].isArray && !textureArraySupported)
{
m_testCtx.getLog() << tcu::TestLog::Message << "GL_OES_texture_storage_multisample_2d_array not supported, skipping type " << samplerTypes[typeNdx].typeStr << tcu::TestLog::EndMessage;
}
else
{
std::map<std::string, std::string> shaderArgs;
shaderArgs["SAMPLERTYPE"] = samplerTypes[typeNdx].typeStr;
shaderArgs["POSITION"] = samplerTypes[typeNdx].samplePosStr;
shaderArgs["EXTENSIONSTATEMENT"] = (samplerTypes[typeNdx].isArray) ? ("#extension GL_OES_texture_storage_multisample_2d_array : require\n") : ("");
{
const std::string fragmentSource = tcu::StringTemplate(fragmentSourceTemplate).specialize(shaderArgs);
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource));
m_testCtx.getLog() << tcu::TestLog::Message << "Building program with uniform sampler of type " << samplerTypes[typeNdx].typeStr << tcu::TestLog::EndMessage;
if (!program.isOk())
{
m_testCtx.getLog() << program;
throw tcu::TestError("could not build shader");
}
// only one uniform -- uniform at index 0
{
int uniforms = 0;
gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORMS, &uniforms);
if (uniforms != 1)
throw tcu::TestError("Unexpected GL_ACTIVE_UNIFORMS, expected 1");
}
m_testCtx.getLog() << tcu::TestLog::Message << "Verifying uniform type." << tcu::TestLog::EndMessage;
// check type
{
const glw::GLuint uniformIndex = 0;
glw::GLint type = 0;
gl.getActiveUniformsiv(program.getProgram(), 1, &uniformIndex, GL_UNIFORM_TYPE, &type);
if (type != (glw::GLint)samplerTypes[typeNdx].glType)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type, expected " << samplerTypes[typeNdx].glType << ", got " << type << tcu::TestLog::EndMessage;
error = true;
}
}
GLU_EXPECT_NO_ERROR(gl.getError(), "");
}
}
}
if (!error)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid uniform type");
return STOP;
}
} // anonymous
ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
: TestCaseGroup(context, "shader", "Shader state query tests")
{
}
ShaderStateQueryTests::~ShaderStateQueryTests (void)
{
}
void ShaderStateQueryTests::init (void)
{
// sampler type query
addChild(new SamplerTypeCase(m_context, "sampler_type", "Sampler type cases"));
}
} // Functional
} // gles31
} // deqp