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
31 using namespace glu;
32
33 namespace deqp
34 {
35
36 typedef void (*SetupUniformsFunc)(const glw::Functions &gl, uint32_t programID, const tcu::Vec4 &constCoords);
37
38 class ShaderFunctionCase : public ShaderRenderCase
39 {
40 public:
41 ShaderFunctionCase(Context &context, const char *name, const char *description, bool isVertexCase,
42 bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc,
43 const char *vertShaderSource, const char *fragShaderSource);
44 ~ShaderFunctionCase(void);
45
46 void init(void);
47 void deinit(void);
48
49 virtual void setupUniforms(uint32_t programID, const tcu::Vec4 &constCoords);
50
51 private:
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
ShaderFunctionCase(Context & context,const char * name,const char * description,bool isVertexCase,bool usesTextures,ShaderEvalFunc evalFunc,SetupUniformsFunc setupUniformsFunc,const char * vertShaderSource,const char * fragShaderSource)61 ShaderFunctionCase::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
~ShaderFunctionCase(void)74 ShaderFunctionCase::~ShaderFunctionCase(void)
75 {
76 }
77
init(void)78 void 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
deinit(void)97 void ShaderFunctionCase::deinit(void)
98 {
99 if (m_usesTexture)
100 {
101 delete m_gradientTexture;
102 }
103 ShaderRenderCase::deinit();
104 }
105
setupUniforms(uint32_t programID,const tcu::Vec4 & constCoords)106 void ShaderFunctionCase::setupUniforms(uint32_t 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
createStructCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion,bool isVertexCase,bool usesTextures,ShaderEvalFunc evalFunc,SetupUniformsFunc setupUniforms,const LineStream & shaderSrc)113 static 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
ShaderFunctionTests(Context & context,glu::GLSLVersion glslVersion)173 ShaderFunctionTests::ShaderFunctionTests(Context &context, glu::GLSLVersion glslVersion)
174 : TestCaseGroup(context, "function", "Function Tests")
175 , m_glslVersion(glslVersion)
176 {
177 }
178
~ShaderFunctionTests(void)179 ShaderFunctionTests::~ShaderFunctionTests(void)
180 {
181 }
182
init(void)183 void ShaderFunctionTests::init(void)
184 {
185 #define FUNCTION_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \
186 do \
187 { \
188 struct Eval_##NAME \
189 { \
190 static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY \
191 }; \
192 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, false, \
193 &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \
194 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, false, \
195 &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \
196 } while (false)
197
198 FUNCTION_CASE(local_variable_aliasing, "Function out parameter aliases local variable",
199 LineStream() << "${HEADER}"
200 << ""
201 << "bool out_params_are_distinct(float x, out float y) {"
202 << " y = 2.;"
203 << " return x == 1. && y == 2.;"
204 << "}"
205 << ""
206 << "void main (void)"
207 << "{"
208 << " float x = 1.;"
209 << " ${DST} = out_params_are_distinct(x, x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);"
210 << " ${ASSIGN_POS}"
211 << "}",
212 { c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); });
213
214 FUNCTION_CASE(
215 global_variable_aliasing, "Function out parameter aliases global variable",
216 LineStream() << "${HEADER}"
217 << ""
218 << "float x = 1.;"
219 << "bool out_params_are_distinct_from_global(out float y) {"
220 << " y = 2.;"
221 << " return x == 1. && y == 2.;"
222 << "}"
223 << ""
224 << "void main (void)"
225 << "{"
226 << " ${DST} = out_params_are_distinct_from_global(x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);"
227 << " ${ASSIGN_POS}"
228 << "}",
229 { c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); });
230 }
231
232 } // namespace deqp
233