| /*------------------------------------------------------------------------- |
| * 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 |