blob: 7266113533947c6231683caefabfb1449b2da327 [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.0 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 struct tests.
*//*--------------------------------------------------------------------*/
#include "es3fShaderFunctionTests.hpp"
#include "glsShaderRenderCase.hpp"
#include "gluTexture.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTextureUtil.hpp"
using namespace deqp::gls;
namespace deqp
{
namespace gles3
{
namespace Functional
{
typedef void (*SetupUniformsFunc)(const glw::Functions &gl, uint32_t programID, const tcu::Vec4 &constCoords);
class ShaderFunctionCase : public ShaderRenderCase
{
public:
ShaderFunctionCase(Context &context, const char *name, const char *description, bool isVertexCase,
bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc,
const char *vertShaderSource, const char *fragShaderSource);
~ShaderFunctionCase(void);
void init(void);
void deinit(void);
virtual void setupUniforms(int programID, const tcu::Vec4 &constCoords);
private:
ShaderFunctionCase(const ShaderFunctionCase &);
ShaderFunctionCase &operator=(const ShaderFunctionCase &);
SetupUniformsFunc m_setupUniforms;
bool m_usesTexture;
glu::Texture2D *m_brickTexture;
};
ShaderFunctionCase::ShaderFunctionCase(Context &context, const char *name, const char *description, bool isVertexCase,
bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc,
const char *vertShaderSource, const char *fragShaderSource)
: ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
description, isVertexCase, evalFunc)
, m_setupUniforms(setupUniformsFunc)
, m_usesTexture(usesTextures)
, m_brickTexture(DE_NULL)
{
m_vertShaderSource = vertShaderSource;
m_fragShaderSource = fragShaderSource;
}
ShaderFunctionCase::~ShaderFunctionCase(void)
{
delete m_brickTexture;
}
void ShaderFunctionCase::init(void)
{
if (m_usesTexture)
{
m_brickTexture = glu::Texture2D::create(m_renderCtx, m_ctxInfo, m_testCtx.getArchive(), "data/brick.png");
m_textures.push_back(TextureBinding(
m_brickTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR)));
DE_ASSERT(m_textures.size() == 1);
}
gls::ShaderRenderCase::init();
}
void ShaderFunctionCase::deinit(void)
{
gls::ShaderRenderCase::deinit();
delete m_brickTexture;
m_brickTexture = DE_NULL;
}
void ShaderFunctionCase::setupUniforms(int programID, const tcu::Vec4 &constCoords)
{
ShaderRenderCase::setupUniforms(programID, constCoords);
if (m_setupUniforms)
m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
}
static ShaderFunctionCase *createStructCase(Context &context, const char *name, const char *description,
bool isVertexCase, bool usesTextures, ShaderEvalFunc evalFunc,
SetupUniformsFunc setupUniforms, const LineStream &shaderSrc,
const std::map<std::string, std::string> *additionalParams)
{
static const char *defaultVertSrc = "#version 300 es\n"
"in highp vec4 a_position;\n"
"in highp vec4 a_coords;\n"
"out mediump vec4 v_coords;\n\n"
"void main (void)\n"
"{\n"
" v_coords = a_coords;\n"
" gl_Position = a_position;\n"
"}\n";
static const char *defaultFragSrc = "#version 300 es\n"
"in mediump vec4 v_color;\n"
"layout(location = 0) out mediump vec4 o_color;\n\n"
"void main (void)\n"
"{\n"
" o_color = v_color;\n"
"}\n";
// Fill in specialization parameters.
std::map<std::string, std::string> spParams;
if (isVertexCase)
{
spParams["HEADER"] = "#version 300 es\n"
"in highp vec4 a_position;\n"
"in highp vec4 a_coords;\n"
"out mediump vec4 v_color;";
spParams["COORDS"] = "a_coords";
spParams["DST"] = "v_color";
spParams["ASSIGN_POS"] = "gl_Position = a_position;";
}
else
{
spParams["HEADER"] = "#version 300 es\n"
"precision mediump float;\n"
"in mediump vec4 v_coords;\n"
"layout(location = 0) out mediump vec4 o_color;";
spParams["COORDS"] = "v_coords";
spParams["DST"] = "o_color";
spParams["ASSIGN_POS"] = "";
}
if (additionalParams)
spParams.insert(additionalParams->begin(), additionalParams->end());
if (isVertexCase)
return new ShaderFunctionCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
tcu::StringTemplate(shaderSrc.str()).specialize(spParams).c_str(),
defaultFragSrc);
else
return new ShaderFunctionCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
defaultVertSrc,
tcu::StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
}
ShaderFunctionTests::ShaderFunctionTests(Context &context) : TestCaseGroup(context, "function", "Function Tests")
{
}
ShaderFunctionTests::~ShaderFunctionTests(void)
{
}
void ShaderFunctionTests::init(void)
{
#define FUNCTION_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, PARAMS) \
do \
{ \
struct Eval_##NAME \
{ \
static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY \
}; /* NOLINT(EVAL_FUNC_BODY) */ \
addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, false, &Eval_##NAME::eval, DE_NULL, \
SHADER_SRC, PARAMS)); \
addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, false, &Eval_##NAME::eval, \
DE_NULL, SHADER_SRC, PARAMS)); \
} while (false)
#define FUNCTION_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \
FUNCTION_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, DE_NULL)
FUNCTION_CASE(local_variable_aliasing, "Function out parameter aliases local variable",
LineStream() << "${HEADER}"
<< ""
<< "bool out_params_are_distinct(float x, out float y) {"
<< " y = 2.;"
<< " return x == 1. && y == 2.;"
<< "}"
<< ""
<< "void main (void)"
<< "{"
<< " float x = 1.;"
<< " ${DST} = out_params_are_distinct(x, x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);"
<< " ${ASSIGN_POS}"
<< "}",
{ c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); });
FUNCTION_CASE(
global_variable_aliasing, "Function out parameter aliases global variable",
LineStream() << "${HEADER}"
<< ""
<< ""
<< "float x = 1.;"
<< "bool out_params_are_distinct_from_global(out float y) {"
<< " y = 2.;"
<< " return x == 1. && y == 2.;"
<< "}"
<< ""
<< "void main (void)"
<< "{"
<< " ${DST} = out_params_are_distinct_from_global(x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);"
<< " ${ASSIGN_POS}"
<< "}",
{ c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); });
}
} // namespace Functional
} // namespace gles3
} // namespace deqp