1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and/or associated documentation files (the
10 * "Materials"), to deal in the Materials without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Materials, and to
13 * permit persons to whom the Materials are furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
19 * The Materials are Confidential Information as defined by the
20 * Khronos Membership Agreement until designated non-confidential by Khronos,
21 * at which point this condition clause shall be removed.
23 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
33 * \brief Shader return statement tests.
34 *//*--------------------------------------------------------------------*/
36 #include "vktShaderRenderReturnTests.hpp"
37 #include "vktShaderRender.hpp"
38 #include "tcuStringTemplate.hpp"
52 RETURNMODE_ALWAYS = 0,
59 // Evaluation functions
60 inline void evalReturnAlways (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
61 inline void evalReturnNever (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(3,2,1); }
62 inline void evalReturnDynamic (ShaderEvalContext& c) { c.color.xyz() = (c.coords.x()+c.coords.y() >= 0.0f) ? c.coords.swizzle(0,1,2) : c.coords.swizzle(3,2,1); }
64 static ShaderEvalFunc getEvalFunc (ReturnMode mode)
68 case RETURNMODE_ALWAYS: return evalReturnAlways;
69 case RETURNMODE_NEVER: return evalReturnNever;
70 case RETURNMODE_DYNAMIC: return evalReturnDynamic;
73 return (ShaderEvalFunc)DE_NULL;
77 class ShaderReturnCase : public ShaderRenderCase
80 ShaderReturnCase (tcu::TestContext& testCtx,
81 const std::string& name,
82 const std::string& description,
84 const std::string& shaderSource,
85 const ShaderEvalFunc evalFunc,
86 const UniformSetup* uniformFunc);
87 virtual ~ShaderReturnCase (void);
90 ShaderReturnCase::ShaderReturnCase (tcu::TestContext& testCtx,
91 const std::string& name,
92 const std::string& description,
94 const std::string& shaderSource,
95 const ShaderEvalFunc evalFunc,
96 const UniformSetup* uniformFunc)
97 : ShaderRenderCase(testCtx, name, description, isVertexCase, evalFunc, uniformFunc, DE_NULL)
101 m_vertShaderSource = shaderSource;
104 "#extension GL_ARB_separate_shader_objects : enable\n"
105 "#extension GL_ARB_shading_language_420pack : enable\n"
106 "layout(location = 0) in mediump vec4 v_color;\n"
107 "layout(location = 0) out mediump vec4 o_color;\n\n"
110 " o_color = v_color;\n"
115 m_fragShaderSource = shaderSource;
118 "#extension GL_ARB_separate_shader_objects : enable\n"
119 "#extension GL_ARB_shading_language_420pack : enable\n"
120 "layout(location = 0) in highp vec4 a_position;\n"
121 "layout(location = 1) in highp vec4 a_coords;\n"
122 "layout(location = 0) out mediump vec4 v_coords;\n\n"
125 " gl_Position = a_position;\n"
126 " v_coords = a_coords;\n"
131 ShaderReturnCase::~ShaderReturnCase (void)
135 class ReturnTestUniformSetup : public UniformSetup
138 ReturnTestUniformSetup (const BaseUniformType uniformType)
139 : m_uniformType(uniformType)
141 virtual void setup (ShaderRenderCaseInstance& instance, const tcu::Vec4&) const
143 instance.useUniform(0u, m_uniformType);
147 const BaseUniformType m_uniformType;
150 // Test case builders.
152 de::MovePtr<ShaderReturnCase> makeConditionalReturnInFuncCase (tcu::TestContext& context, const std::string& name, const std::string& description, ReturnMode returnMode, bool isVertex)
154 tcu::StringTemplate tmpl(
156 "#extension GL_ARB_separate_shader_objects : enable\n"
157 "#extension GL_ARB_shading_language_420pack : enable\n"
158 "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
160 "${COORDPREC} vec4 getColor (void)\n"
162 " if (${RETURNCOND})\n"
163 " return vec4(${COORDS}.xyz, 1.0);\n"
164 " return vec4(${COORDS}.wzy, 1.0);\n"
169 " ${OUTPUT} = getColor();\n"
172 const char* coords = isVertex ? "a_coords" : "v_coords";
174 std::map<std::string, std::string> params;
176 params["COORDLOC"] = isVertex ? "1" : "0";
177 params["COORDPREC"] = isVertex ? "highp" : "mediump";
178 params["OUTPUT"] = isVertex ? "v_color" : "o_color";
179 params["COORDS"] = coords;
180 params["EXTRADECL"] = isVertex ? "layout(location = 0) in highp vec4 a_position;\nlayout(location = 0) out mediump vec4 v_color;\n" : "layout(location = 0) out mediump vec4 o_color;\n";
181 params["POSITIONWRITE"] = isVertex ? " gl_Position = a_position;\n" : "";
185 case RETURNMODE_ALWAYS: params["RETURNCOND"] = "true"; break;
186 case RETURNMODE_NEVER: params["RETURNCOND"] = "false"; break;
187 case RETURNMODE_DYNAMIC: params["RETURNCOND"] = std::string(coords) + ".x+" + coords + ".y >= 0.0"; break;
188 default: DE_ASSERT(DE_FALSE);
191 return de::MovePtr<ShaderReturnCase>(new ShaderReturnCase(context, name, description, isVertex, tmpl.specialize(params), getEvalFunc(returnMode), DE_NULL));
194 de::MovePtr<ShaderReturnCase> makeOutputWriteReturnCase (tcu::TestContext& context, const std::string& name, const std::string& description, bool inFunction, ReturnMode returnMode, bool isVertex)
196 tcu::StringTemplate tmpl(
200 "#extension GL_ARB_separate_shader_objects : enable\n"
201 "#extension GL_ARB_shading_language_420pack : enable\n"
202 "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
204 "void myfunc (void)\n"
206 " ${OUTPUT} = vec4(${COORDS}.xyz, 1.0);\n"
207 " if (${RETURNCOND})\n"
209 " ${OUTPUT} = vec4(${COORDS}.wzy, 1.0);\n"
218 "#extension GL_ARB_separate_shader_objects : enable\n"
219 "#extension GL_ARB_shading_language_420pack : enable\n"
220 "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
225 " ${OUTPUT} = vec4(${COORDS}.xyz, 1.0);\n"
226 " if (${RETURNCOND})\n"
228 " ${OUTPUT} = vec4(${COORDS}.wzy, 1.0);\n"
231 const char* coords = isVertex ? "a_coords" : "v_coords";
233 std::map<std::string, std::string> params;
235 params["COORDLOC"] = isVertex ? "1" : "0";
236 params["COORDPREC"] = isVertex ? "highp" : "mediump";
237 params["COORDS"] = coords;
238 params["OUTPUT"] = isVertex ? "v_color" : "o_color";
239 params["EXTRADECL"] = isVertex ? "layout(location = 0) in highp vec4 a_position;\nlayout(location = 0) out mediump vec4 v_color;\n" : "layout(location = 0) out mediump vec4 o_color;\n";
240 params["POSITIONWRITE"] = isVertex ? " gl_Position = a_position;\n" : "";
244 case RETURNMODE_ALWAYS: params["RETURNCOND"] = "true"; break;
245 case RETURNMODE_NEVER: params["RETURNCOND"] = "false"; break;
246 case RETURNMODE_DYNAMIC: params["RETURNCOND"] = std::string(coords) + ".x+" + coords + ".y >= 0.0"; break;
247 default: DE_ASSERT(DE_FALSE);
250 return de::MovePtr<ShaderReturnCase>(new ShaderReturnCase(context, name, description, isVertex, tmpl.specialize(params), getEvalFunc(returnMode), DE_NULL));
253 de::MovePtr<ShaderReturnCase> makeReturnInLoopCase (tcu::TestContext& context, const std::string& name, const std::string& description, bool isDynamicLoop, ReturnMode returnMode, bool isVertex)
255 tcu::StringTemplate tmpl(
257 "#extension GL_ARB_separate_shader_objects : enable\n"
258 "#extension GL_ARB_shading_language_420pack : enable\n"
259 "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
260 "layout(binding = 0, std140) uniform something { mediump int ui_one; };\n"
262 "${COORDPREC} vec4 getCoords (void)\n"
264 " ${COORDPREC} vec4 coords = ${COORDS};\n"
265 " for (int i = 0; i < ${ITERLIMIT}; i++)\n"
267 " if (${RETURNCOND})\n"
269 " coords = coords.wzyx;\n"
276 " ${OUTPUT} = vec4(getCoords().xyz, 1.0);\n"
279 const char* coords = isVertex ? "a_coords" : "v_coords";
281 std::map<std::string, std::string> params;
283 params["COORDLOC"] = isVertex ? "1" : "0";
284 params["COORDPREC"] = isVertex ? "highp" : "mediump";
285 params["OUTPUT"] = isVertex ? "v_color" : "o_color";
286 params["COORDS"] = coords;
287 params["EXTRADECL"] = isVertex ? "layout(location = 0) in highp vec4 a_position;\nlayout(location = 0) out mediump vec4 v_color;\n" : "layout(location = 0) out mediump vec4 o_color;\n";
288 params["POSITIONWRITE"] = isVertex ? " gl_Position = a_position;\n" : "";
289 params["ITERLIMIT"] = isDynamicLoop ? "ui_one" : "1";
293 case RETURNMODE_ALWAYS: params["RETURNCOND"] = "true"; break;
294 case RETURNMODE_NEVER: params["RETURNCOND"] = "false"; break;
295 case RETURNMODE_DYNAMIC: params["RETURNCOND"] = std::string(coords) + ".x+" + coords + ".y >= 0.0"; break;
296 default: DE_ASSERT(DE_FALSE);
299 return de::MovePtr<ShaderReturnCase>(new ShaderReturnCase(context, name, description, isVertex, tmpl.specialize(params), getEvalFunc(returnMode), new ReturnTestUniformSetup(UI_ONE)));
302 static const char* getReturnModeName (ReturnMode mode)
306 case RETURNMODE_ALWAYS: return "always";
307 case RETURNMODE_NEVER: return "never";
308 case RETURNMODE_DYNAMIC: return "dynamic";
315 static const char* getReturnModeDesc (ReturnMode mode)
319 case RETURNMODE_ALWAYS: return "Always return";
320 case RETURNMODE_NEVER: return "Never return";
321 case RETURNMODE_DYNAMIC: return "Return based on coords";
328 class ShaderReturnTests : public tcu::TestCaseGroup
331 ShaderReturnTests (tcu::TestContext& context);
332 virtual ~ShaderReturnTests (void);
333 virtual void init (void);
336 ShaderReturnTests (const ShaderReturnTests&); // not allowed!
337 ShaderReturnTests& operator= (const ShaderReturnTests&); // not allowed!
340 ShaderReturnTests::ShaderReturnTests (tcu::TestContext& context)
341 : TestCaseGroup(context, "return", "Return Statement Tests")
345 ShaderReturnTests::~ShaderReturnTests (void)
349 void ShaderReturnTests::init (void)
351 addChild(new ShaderReturnCase(m_testCtx, "single_return_vertex", "Single return statement in function", true,
353 "#extension GL_ARB_separate_shader_objects : enable\n"
354 "#extension GL_ARB_shading_language_420pack : enable\n"
355 "layout(location = 0) in highp vec4 a_position;\n"
356 "layout(location = 1) in highp vec4 a_coords;\n"
357 "layout(location = 0) out highp vec4 v_color;\n\n"
358 "vec4 getColor (void)\n"
360 " return vec4(a_coords.xyz, 1.0);\n"
364 " gl_Position = a_position;\n"
365 " v_color = getColor();\n"
366 "}\n", evalReturnAlways, DE_NULL));
367 addChild(new ShaderReturnCase(m_testCtx, "single_return_fragment", "Single return statement in function", false,
369 "#extension GL_ARB_separate_shader_objects : enable\n"
370 "#extension GL_ARB_shading_language_420pack : enable\n"
371 "layout(location = 0) in mediump vec4 v_coords;\n"
372 "layout(location = 0) out mediump vec4 o_color;\n"
373 "mediump vec4 getColor (void)\n"
375 " return vec4(v_coords.xyz, 1.0);\n"
379 " o_color = getColor();\n"
380 "}\n", evalReturnAlways, DE_NULL));
382 // Conditional return statement in function.
383 for (int returnMode = 0; returnMode < RETURNMODE_LAST; returnMode++)
385 for (int isFragment = 0; isFragment < 2; isFragment++)
387 std::string name = std::string("conditional_return_") + getReturnModeName((ReturnMode)returnMode) + (isFragment ? "_fragment" : "_vertex");
388 std::string description = std::string(getReturnModeDesc((ReturnMode)returnMode)) + " in function";
389 de::MovePtr<ShaderReturnCase> testCase (makeConditionalReturnInFuncCase(m_testCtx, name, description, (ReturnMode)returnMode, isFragment == 0));
390 addChild(testCase.release());
394 // Unconditional double return in function.
395 addChild(new ShaderReturnCase(m_testCtx, "double_return_vertex", "Unconditional double return in function", true,
397 "#extension GL_ARB_separate_shader_objects : enable\n"
398 "#extension GL_ARB_shading_language_420pack : enable\n"
399 "layout(location = 0) in highp vec4 a_position;\n"
400 "layout(location = 1) in highp vec4 a_coords;\n"
401 "layout(location = 0) out highp vec4 v_color;\n\n"
402 "vec4 getColor (void)\n"
404 " return vec4(a_coords.xyz, 1.0);\n"
405 " return vec4(a_coords.wzy, 1.0);\n"
409 " gl_Position = a_position;\n"
410 " v_color = getColor();\n"
411 "}\n", evalReturnAlways, DE_NULL));
412 addChild(new ShaderReturnCase(m_testCtx, "double_return_fragment", "Unconditional double return in function", false,
414 "#extension GL_ARB_separate_shader_objects : enable\n"
415 "#extension GL_ARB_shading_language_420pack : enable\n"
416 "layout(location = 0) in mediump vec4 v_coords;\n"
417 "layout(location = 0) out mediump vec4 o_color;\n\n"
418 "mediump vec4 getColor (void)\n"
420 " return vec4(v_coords.xyz, 1.0);\n"
421 " return vec4(v_coords.wzy, 1.0);\n"
425 " o_color = getColor();\n"
426 "}\n", evalReturnAlways, DE_NULL));
428 // Last statement in main.
429 addChild(new ShaderReturnCase(m_testCtx, "last_statement_in_main_vertex", "Return as a final statement in main()", true,
431 "#extension GL_ARB_separate_shader_objects : enable\n"
432 "#extension GL_ARB_shading_language_420pack : enable\n"
433 "layout(location = 0) in highp vec4 a_position;\n"
434 "layout(location = 1) in highp vec4 a_coords;\n"
435 "layout(location = 0) out highp vec4 v_color;\n\n"
438 " gl_Position = a_position;\n"
439 " v_color = vec4(a_coords.xyz, 1.0);\n"
441 "}\n", evalReturnAlways, DE_NULL));
442 addChild(new ShaderReturnCase(m_testCtx, "last_statement_in_main_fragment", "Return as a final statement in main()", false,
444 "#extension GL_ARB_separate_shader_objects : enable\n"
445 "#extension GL_ARB_shading_language_420pack : enable\n"
446 "layout(location = 0) in mediump vec4 v_coords;\n"
447 "layout(location = 0) out mediump vec4 o_color;\n\n"
450 " o_color = vec4(v_coords.xyz, 1.0);\n"
452 "}\n", evalReturnAlways, DE_NULL));
454 // Return between output variable writes.
455 for (int inFunc = 0; inFunc < 2; inFunc++)
457 for (int returnMode = 0; returnMode < RETURNMODE_LAST; returnMode++)
459 for (int isFragment = 0; isFragment < 2; isFragment++)
461 std::string name = std::string("output_write_") + (inFunc ? "in_func_" : "") + getReturnModeName((ReturnMode)returnMode) + (isFragment ? "_fragment" : "_vertex");
462 std::string desc = std::string(getReturnModeDesc((ReturnMode)returnMode)) + (inFunc ? " in user-defined function" : " in main()") + " between output writes";
463 de::MovePtr<ShaderReturnCase> testCase = (makeOutputWriteReturnCase(m_testCtx, name, desc, inFunc != 0, (ReturnMode)returnMode, isFragment == 0));
464 addChild(testCase.release());
469 // Conditional return statement in loop.
470 for (int isDynamicLoop = 0; isDynamicLoop < 2; isDynamicLoop++)
472 for (int returnMode = 0; returnMode < RETURNMODE_LAST; returnMode++)
474 for (int isFragment = 0; isFragment < 2; isFragment++)
476 std::string name = std::string("return_in_") + (isDynamicLoop ? "dynamic" : "static") + "_loop_" + getReturnModeName((ReturnMode)returnMode) + (isFragment ? "_fragment" : "_vertex");
477 std::string description = std::string(getReturnModeDesc((ReturnMode)returnMode)) + " in loop";
478 de::MovePtr<ShaderReturnCase> testCase (makeReturnInLoopCase(m_testCtx, name, description, isDynamicLoop != 0, (ReturnMode)returnMode, isFragment == 0));
479 addChild(testCase.release());
484 // Unconditional return in infinite loop.
485 addChild(new ShaderReturnCase(m_testCtx, "return_in_infinite_loop_vertex", "Return in infinite loop", true,
487 "#extension GL_ARB_separate_shader_objects : enable\n"
488 "#extension GL_ARB_shading_language_420pack : enable\n"
489 "layout(location = 0) in highp vec4 a_position;\n"
490 "layout(location = 1) in highp vec4 a_coords;\n"
491 "layout(location = 0) out highp vec4 v_color;\n"
492 "layout(binding = 0, std140) uniform something { int ui_zero; };\n"
493 "highp vec4 getCoords (void)\n"
495 " for (int i = 1; i < 10; i += ui_zero)\n"
496 " return a_coords;\n"
497 " return a_coords.wzyx;\n"
501 " gl_Position = a_position;\n"
502 " v_color = vec4(getCoords().xyz, 1.0);\n"
504 "}\n", evalReturnAlways, new ReturnTestUniformSetup(UI_ZERO)));
505 addChild(new ShaderReturnCase(m_testCtx, "return_in_infinite_loop_fragment", "Return in infinite loop", false,
507 "#extension GL_ARB_separate_shader_objects : enable\n"
508 "#extension GL_ARB_shading_language_420pack : enable\n"
509 "layout(location = 0) in mediump vec4 v_coords;\n"
510 "layout(location = 0) out mediump vec4 o_color;\n"
511 "layout(binding = 0, std140) uniform something { int ui_zero; };\n\n"
512 "mediump vec4 getCoords (void)\n"
514 " for (int i = 1; i < 10; i += ui_zero)\n"
515 " return v_coords;\n"
516 " return v_coords.wzyx;\n"
520 " o_color = vec4(getCoords().xyz, 1.0);\n"
522 "}\n", evalReturnAlways, new ReturnTestUniformSetup(UI_ZERO)));
527 tcu::TestCaseGroup* createReturnTests (tcu::TestContext& testCtx)
529 return new ShaderReturnTests(testCtx);