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