1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Shader struct tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es3fShaderFunctionTests.hpp" 25#include "glsShaderRenderCase.hpp" 26#include "gluTexture.hpp" 27#include "tcuStringTemplate.hpp" 28#include "tcuTextureUtil.hpp" 29 30using namespace deqp::gls; 31 32namespace deqp 33{ 34namespace gles3 35{ 36namespace Functional 37{ 38 39typedef void (*SetupUniformsFunc) (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords); 40 41class ShaderFunctionCase : public ShaderRenderCase 42{ 43public: 44 ShaderFunctionCase (Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource); 45 ~ShaderFunctionCase (void); 46 47 void init (void); 48 void deinit (void); 49 50 virtual void setupUniforms (int programID, const tcu::Vec4& constCoords); 51 52private: 53 ShaderFunctionCase (const ShaderFunctionCase&); 54 ShaderFunctionCase& operator= (const ShaderFunctionCase&); 55 56 SetupUniformsFunc m_setupUniforms; 57 bool m_usesTexture; 58 59 glu::Texture2D* m_brickTexture; 60}; 61 62ShaderFunctionCase::ShaderFunctionCase (Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource) 63 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc) 64 , m_setupUniforms (setupUniformsFunc) 65 , m_usesTexture (usesTextures) 66 , m_brickTexture (DE_NULL) 67{ 68 m_vertShaderSource = vertShaderSource; 69 m_fragShaderSource = fragShaderSource; 70} 71 72ShaderFunctionCase::~ShaderFunctionCase (void) 73{ 74 delete m_brickTexture; 75} 76 77void ShaderFunctionCase::init (void) 78{ 79 if (m_usesTexture) 80 { 81 m_brickTexture = glu::Texture2D::create(m_renderCtx, m_ctxInfo, m_testCtx.getArchive(), "data/brick.png"); 82 m_textures.push_back(TextureBinding(m_brickTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, 83 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR))); 84 DE_ASSERT(m_textures.size() == 1); 85 } 86 gls::ShaderRenderCase::init(); 87} 88 89void ShaderFunctionCase::deinit (void) 90{ 91 gls::ShaderRenderCase::deinit(); 92 delete m_brickTexture; 93 m_brickTexture = DE_NULL; 94} 95 96void ShaderFunctionCase::setupUniforms (int programID, const tcu::Vec4& constCoords) 97{ 98 ShaderRenderCase::setupUniforms(programID, constCoords); 99 if (m_setupUniforms) 100 m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords); 101} 102 103static 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) 104{ 105 static const char* defaultVertSrc = 106 "#version 300 es\n" 107 "in highp vec4 a_position;\n" 108 "in highp vec4 a_coords;\n" 109 "out mediump vec4 v_coords;\n\n" 110 "void main (void)\n" 111 "{\n" 112 " v_coords = a_coords;\n" 113 " gl_Position = a_position;\n" 114 "}\n"; 115 static const char* defaultFragSrc = 116 "#version 300 es\n" 117 "in mediump vec4 v_color;\n" 118 "layout(location = 0) out mediump vec4 o_color;\n\n" 119 "void main (void)\n" 120 "{\n" 121 " o_color = v_color;\n" 122 "}\n"; 123 124 // Fill in specialization parameters. 125 std::map<std::string, std::string> spParams; 126 if (isVertexCase) 127 { 128 spParams["HEADER"] = 129 "#version 300 es\n" 130 "in highp vec4 a_position;\n" 131 "in highp vec4 a_coords;\n" 132 "out mediump vec4 v_color;"; 133 spParams["COORDS"] = "a_coords"; 134 spParams["DST"] = "v_color"; 135 spParams["ASSIGN_POS"] = "gl_Position = a_position;"; 136 } 137 else 138 { 139 spParams["HEADER"] = 140 "#version 300 es\n" 141 "precision mediump float;\n" 142 "in mediump vec4 v_coords;\n" 143 "layout(location = 0) out mediump vec4 o_color;"; 144 spParams["COORDS"] = "v_coords"; 145 spParams["DST"] = "o_color"; 146 spParams["ASSIGN_POS"] = ""; 147 } 148 if (additionalParams) 149 spParams.insert(additionalParams->begin(), additionalParams->end()); 150 151 if (isVertexCase) 152 return new ShaderFunctionCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, tcu::StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), defaultFragSrc); 153 else 154 return new ShaderFunctionCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, defaultVertSrc, tcu::StringTemplate(shaderSrc.str()).specialize(spParams).c_str()); 155} 156 157ShaderFunctionTests::ShaderFunctionTests (Context& context) 158 : TestCaseGroup(context, "function", "Function Tests") 159{ 160} 161 162ShaderFunctionTests::~ShaderFunctionTests (void) 163{ 164} 165 166void ShaderFunctionTests::init (void) 167{ 168 #define FUNCTION_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, PARAMS) \ 169 do { \ 170 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \ 171 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, false, &Eval_##NAME::eval, DE_NULL, SHADER_SRC, PARAMS)); \ 172 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, false,&Eval_##NAME::eval, DE_NULL, SHADER_SRC, PARAMS));\ 173 } while (deGetFalse()) 174 175 #define FUNCTION_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \ 176 FUNCTION_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, DE_NULL) 177 178 FUNCTION_CASE(local_variable_aliasing, "Function out parameter aliases local variable", 179 LineStream() 180 << "${HEADER}" 181 << "" 182 << "bool out_params_are_distinct(float x, out float y) {" 183 << " y = 2.;" 184 << " return x == 1. && y == 2.;" 185 << "}" 186 << "" 187 << "void main (void)" 188 << "{" 189 << " float x = 1.;" 190 << " ${DST} = out_params_are_distinct(x, x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);" 191 << " ${ASSIGN_POS}" 192 << "}", 193 { c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); }); 194 195 FUNCTION_CASE(global_variable_aliasing, "Function out parameter aliases global variable", 196 LineStream() 197 << "${HEADER}" 198 << "" 199 << "" 200 << "float x = 1.;" 201 << "bool out_params_are_distinct_from_global(out float y) {" 202 << " y = 2.;" 203 << " return x == 1. && y == 2.;" 204 << "}" 205 << "" 206 << "void main (void)" 207 << "{" 208 << " ${DST} = out_params_are_distinct_from_global(x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);" 209 << " ${ASSIGN_POS}" 210 << "}", 211 { c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); }); 212} 213 214} // Functional 215} // gles3 216} // deqp 217