| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2016 Google Inc. |
| * Copyright (c) 2016 The Khronos Group Inc. |
| * |
| * 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 "glcShaderStructTests.hpp" |
| #include "glcShaderRenderCase.hpp" |
| #include "gluTexture.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| #include "tcuStringTemplate.hpp" |
| #include "tcuTextureUtil.hpp" |
| |
| using tcu::StringTemplate; |
| |
| using std::string; |
| using std::vector; |
| using std::ostringstream; |
| |
| using namespace glu; |
| |
| namespace deqp |
| { |
| |
| enum |
| { |
| TEXTURE_GRADIENT = 0 //!< Unit index for gradient texture |
| }; |
| |
| typedef void (*SetupUniformsFunc)(const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords); |
| |
| class ShaderStructCase : public ShaderRenderCase |
| { |
| public: |
| ShaderStructCase(Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures, |
| ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, |
| const char* fragShaderSource); |
| ~ShaderStructCase(void); |
| |
| void init(void); |
| void deinit(void); |
| |
| virtual void setupUniforms(deUint32 programID, const tcu::Vec4& constCoords); |
| |
| private: |
| ShaderStructCase(const ShaderStructCase&); |
| ShaderStructCase& operator=(const ShaderStructCase&); |
| |
| SetupUniformsFunc m_setupUniforms; |
| bool m_usesTexture; |
| |
| glu::Texture2D* m_gradientTexture; |
| }; |
| |
| ShaderStructCase::ShaderStructCase(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_gradientTexture(DE_NULL) |
| { |
| m_vertShaderSource = vertShaderSource; |
| m_fragShaderSource = fragShaderSource; |
| } |
| |
| ShaderStructCase::~ShaderStructCase(void) |
| { |
| } |
| |
| void ShaderStructCase::init(void) |
| { |
| if (m_usesTexture) |
| { |
| m_gradientTexture = new glu::Texture2D(m_renderCtx, GL_RGBA8, 128, 128); |
| |
| m_gradientTexture->getRefTexture().allocLevel(0); |
| tcu::fillWithComponentGradients(m_gradientTexture->getRefTexture().getLevel(0), tcu::Vec4(0.0f), |
| tcu::Vec4(1.0f)); |
| m_gradientTexture->upload(); |
| |
| m_textures.push_back(TextureBinding( |
| m_gradientTexture, 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); |
| } |
| ShaderRenderCase::init(); |
| } |
| |
| void ShaderStructCase::deinit(void) |
| { |
| if (m_usesTexture) |
| { |
| delete m_gradientTexture; |
| } |
| ShaderRenderCase::deinit(); |
| } |
| |
| void ShaderStructCase::setupUniforms(deUint32 programID, const tcu::Vec4& constCoords) |
| { |
| ShaderRenderCase::setupUniforms(programID, constCoords); |
| if (m_setupUniforms) |
| m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords); |
| } |
| |
| static ShaderStructCase* createStructCase(Context& context, const char* name, const char* description, |
| glu::GLSLVersion glslVersion, bool isVertexCase, bool usesTextures, |
| ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms, |
| const LineStream& shaderSrc) |
| { |
| const std::string versionDecl = glu::getGLSLVersionDeclaration(glslVersion); |
| |
| const std::string defaultVertSrc = versionDecl + "\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"; |
| const std::string defaultFragSrc = versionDecl + "\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"] = versionDecl + "\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"] = versionDecl + "\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 (isVertexCase) |
| return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, |
| StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), |
| defaultFragSrc.c_str()); |
| else |
| return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms, |
| defaultVertSrc.c_str(), |
| StringTemplate(shaderSrc.str()).specialize(spParams).c_str()); |
| } |
| |
| class LocalStructTests : public TestCaseGroup |
| { |
| public: |
| LocalStructTests(Context& context, glu::GLSLVersion glslVersion) |
| : TestCaseGroup(context, "local", "Local structs"), m_glslVersion(glslVersion) |
| { |
| } |
| |
| ~LocalStructTests(void) |
| { |
| } |
| |
| virtual void init(void); |
| |
| private: |
| glu::GLSLVersion m_glslVersion; |
| }; |
| |
| void LocalStructTests::init(void) |
| { |
| #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY) \ |
| do \ |
| { \ |
| struct Eval_##NAME \ |
| { \ |
| static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY \ |
| }; \ |
| addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, false, \ |
| &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \ |
| addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, false, \ |
| &Eval_##NAME::eval, DE_NULL, SHADER_SRC)); \ |
| } while (deGetFalse()) |
| |
| LOCAL_STRUCT_CASE(basic, "Basic struct usage", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" |
| << " s.b = ${COORDS}.yzw;" |
| << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); |
| |
| LOCAL_STRUCT_CASE(nested, "Nested struct", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" |
| << " s.b = T(ui_zero, ${COORDS}.yz);" |
| << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); |
| |
| LOCAL_STRUCT_CASE(array_member, "Struct with array member", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump float b[3];" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s;" |
| << " s.a = ${COORDS}.w;" |
| << " s.c = ui_one;" |
| << " s.b[0] = ${COORDS}.z;" |
| << " s.b[1] = ${COORDS}.y;" |
| << " s.b[2] = ${COORDS}.x;" |
| << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); |
| |
| LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump float b[3];" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s;" |
| << " s.a = ${COORDS}.w;" |
| << " s.c = ui_one;" |
| << " s.b[0] = ${COORDS}.z;" |
| << " s.b[1] = ${COORDS}.y;" |
| << " s.b[2] = ${COORDS}.x;" |
| << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(1, 2, 0); }); |
| |
| LOCAL_STRUCT_CASE(struct_array, "Struct array", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[3];" |
| << " s[0] = S(${COORDS}.x, ui_zero);" |
| << " s[1].a = ${COORDS}.y;" |
| << " s[1].b = ui_one;" |
| << " s[2] = S(${COORDS}.z, ui_two);" |
| << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); |
| |
| LOCAL_STRUCT_CASE( |
| struct_array_dynamic_index, "Struct array with dynamic indexing", |
| LineStream() |
| << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[3];" |
| << " s[0] = S(${COORDS}.x, ui_zero);" |
| << " s[1].a = ${COORDS}.y;" |
| << " s[1].b = ui_one;" |
| << " s[2] = S(${COORDS}.z, ui_two);" |
| << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); |
| |
| LOCAL_STRUCT_CASE( |
| nested_struct_array, "Nested struct array", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform mediump float uf_two;" |
| << "uniform mediump float uf_three;" |
| << "uniform mediump float uf_four;" |
| << "uniform mediump float uf_half;" |
| << "uniform mediump float uf_third;" |
| << "uniform mediump float uf_fourth;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[2];" |
| << "" |
| << " // S[0]" |
| << " s[0].a = ${COORDS}.x;" |
| << " s[0].b[0].a = uf_half;" |
| << " s[0].b[0].b[0] = ${COORDS}.xy;" |
| << " s[0].b[0].b[1] = ${COORDS}.zw;" |
| << " s[0].b[1].a = uf_third;" |
| << " s[0].b[1].b[0] = ${COORDS}.zw;" |
| << " s[0].b[1].b[1] = ${COORDS}.xy;" |
| << " s[0].b[2].a = uf_fourth;" |
| << " s[0].b[2].b[0] = ${COORDS}.xz;" |
| << " s[0].b[2].b[1] = ${COORDS}.yw;" |
| << " s[0].c = ui_zero;" |
| << "" |
| << " // S[1]" |
| << " s[1].a = ${COORDS}.w;" |
| << " s[1].b[0].a = uf_two;" |
| << " s[1].b[0].b[0] = ${COORDS}.xx;" |
| << " s[1].b[0].b[1] = ${COORDS}.yy;" |
| << " s[1].b[1].a = uf_three;" |
| << " s[1].b[1].b[0] = ${COORDS}.zz;" |
| << " s[1].b[1].b[1] = ${COORDS}.ww;" |
| << " s[1].b[2].a = uf_four;" |
| << " s[1].b[2].b[0] = ${COORDS}.yx;" |
| << " s[1].b[2].b[1] = ${COORDS}.wz;" |
| << " s[1].c = ui_one;" |
| << "" |
| << " mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5" |
| << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" |
| << " mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w " |
| "+ w) * 0.333" |
| << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" |
| << " ${DST} = vec4(r, g, b, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(2, 0, 3); }); |
| |
| LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform mediump float uf_two;" |
| << "uniform mediump float uf_three;" |
| << "uniform mediump float uf_four;" |
| << "uniform mediump float uf_half;" |
| << "uniform mediump float uf_third;" |
| << "uniform mediump float uf_fourth;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[2];" |
| << "" |
| << " // S[0]" |
| << " s[0].a = ${COORDS}.x;" |
| << " s[0].b[0].a = uf_half;" |
| << " s[0].b[0].b[0] = ${COORDS}.xy;" |
| << " s[0].b[0].b[1] = ${COORDS}.zw;" |
| << " s[0].b[1].a = uf_third;" |
| << " s[0].b[1].b[0] = ${COORDS}.zw;" |
| << " s[0].b[1].b[1] = ${COORDS}.xy;" |
| << " s[0].b[2].a = uf_fourth;" |
| << " s[0].b[2].b[0] = ${COORDS}.xz;" |
| << " s[0].b[2].b[1] = ${COORDS}.yw;" |
| << " s[0].c = ui_zero;" |
| << "" |
| << " // S[1]" |
| << " s[1].a = ${COORDS}.w;" |
| << " s[1].b[0].a = uf_two;" |
| << " s[1].b[0].b[0] = ${COORDS}.xx;" |
| << " s[1].b[0].b[1] = ${COORDS}.yy;" |
| << " s[1].b[1].a = uf_three;" |
| << " s[1].b[1].b[0] = ${COORDS}.zz;" |
| << " s[1].b[1].b[1] = ${COORDS}.ww;" |
| << " s[1].b[2].a = uf_four;" |
| << " s[1].b[2].b[0] = ${COORDS}.yx;" |
| << " s[1].b[2].b[1] = ${COORDS}.wz;" |
| << " s[1].c = ui_one;" |
| << "" |
| << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + " |
| "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5" |
| << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * " |
| "s[ui_one].b[2].a; // x * 0.25 * 4" |
| << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + " |
| "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + " |
| "w + w) * 0.333" |
| << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - " |
| "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0" |
| << " ${DST} = vec4(r, g, b, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(2, 0, 3); }); |
| |
| LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "mediump vec4 myFunc (S s)" |
| << "{" |
| << " return vec4(s.a, s.b.x, s.b.y, s.c);" |
| << "}" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" |
| << " s.b = ${COORDS}.yzw;" |
| << " ${DST} = myFunc(s);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); |
| |
| LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "mediump vec4 myFunc (S s)" |
| << "{" |
| << " return vec4(s.a, s.b.b, s.b.a + s.c);" |
| << "}" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" |
| << " s.b = T(ui_zero, ${COORDS}.yz);" |
| << " ${DST} = myFunc(s);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); |
| |
| LOCAL_STRUCT_CASE(return, "Struct as a return value", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "S myFunc (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" |
| << " s.b = ${COORDS}.yzw;" |
| << " return s;" |
| << "}" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = myFunc();" |
| << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); |
| |
| LOCAL_STRUCT_CASE(return_nested, "Nested struct", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "S myFunc (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" |
| << " s.b = T(ui_zero, ${COORDS}.yz);" |
| << " return s;" |
| << "}" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = myFunc();" |
| << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 1, 2); }); |
| |
| LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform mediump float uf_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" |
| << " if (uf_one > 0.0)" |
| << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" |
| << " ${DST} = vec4(s.a, s.b.xy, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); |
| |
| LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" |
| << " for (int i = 0; i < 3; i++)" |
| << " {" |
| << " if (i == 1)" |
| << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" |
| << " }" |
| << " ${DST} = vec4(s.a, s.b.xy, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); |
| |
| LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_three;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" |
| << " for (int i = 0; i < ui_three; i++)" |
| << " {" |
| << " if (i == ui_one)" |
| << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" |
| << " }" |
| << " ${DST} = vec4(s.a, s.b.xy, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(3, 2, 1); }); |
| |
| LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform mediump float uf_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" |
| << " if (uf_one > 0.0)" |
| << " s.b = T(ui_zero, ${COORDS}.zw);" |
| << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 2, 3); }); |
| |
| LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform mediump float uf_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" |
| << " for (int i = 0; i < 3; i++)" |
| << " {" |
| << " if (i == 1)" |
| << " s.b = T(ui_zero, ${COORDS}.zw);" |
| << " }" |
| << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 2, 3); }); |
| |
| LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_three;" |
| << "uniform mediump float uf_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" |
| << " for (int i = 0; i < ui_three; i++)" |
| << " {" |
| << " if (i == ui_one)" |
| << " s.b = T(ui_zero, ${COORDS}.zw);" |
| << " }" |
| << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(0, 2, 3); }); |
| |
| LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[3];" |
| << " s[0] = S(${COORDS}.x, ui_zero);" |
| << " s[1].a = ${COORDS}.y;" |
| << " s[1].b = -ui_one;" |
| << " s[2] = S(${COORDS}.z, ui_two);" |
| << "" |
| << " mediump float rgb[3];" |
| << " int alpha = 0;" |
| << " for (int i = 0; i < 3; i++)" |
| << " {" |
| << " rgb[i] = s[2-i].a;" |
| << " alpha += s[i].b;" |
| << " }" |
| << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); |
| |
| LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform mediump float uf_two;" |
| << "uniform mediump float uf_three;" |
| << "uniform mediump float uf_four;" |
| << "uniform mediump float uf_half;" |
| << "uniform mediump float uf_third;" |
| << "uniform mediump float uf_fourth;" |
| << "uniform mediump float uf_sixth;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[2];" |
| << "" |
| << " // S[0]" |
| << " s[0].a = ${COORDS}.x;" |
| << " s[0].b[0].a = uf_half;" |
| << " s[0].b[0].b[0] = ${COORDS}.yx;" |
| << " s[0].b[0].b[1] = ${COORDS}.zx;" |
| << " s[0].b[1].a = uf_third;" |
| << " s[0].b[1].b[0] = ${COORDS}.yy;" |
| << " s[0].b[1].b[1] = ${COORDS}.wy;" |
| << " s[0].b[2].a = uf_fourth;" |
| << " s[0].b[2].b[0] = ${COORDS}.zx;" |
| << " s[0].b[2].b[1] = ${COORDS}.zy;" |
| << " s[0].c = ui_zero;" |
| << "" |
| << " // S[1]" |
| << " s[1].a = ${COORDS}.w;" |
| << " s[1].b[0].a = uf_two;" |
| << " s[1].b[0].b[0] = ${COORDS}.zx;" |
| << " s[1].b[0].b[1] = ${COORDS}.zy;" |
| << " s[1].b[1].a = uf_three;" |
| << " s[1].b[1].b[0] = ${COORDS}.zz;" |
| << " s[1].b[1].b[1] = ${COORDS}.ww;" |
| << " s[1].b[2].a = uf_four;" |
| << " s[1].b[2].b[0] = ${COORDS}.yx;" |
| << " s[1].b[2].b[1] = ${COORDS}.wz;" |
| << " s[1].c = ui_one;" |
| << "" |
| << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" |
| << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" |
| << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" |
| << " mediump float a = 1.0;" |
| << " for (int i = 0; i < 2; i++)" |
| << " {" |
| << " for (int j = 0; j < 3; j++)" |
| << " {" |
| << " r += s[0].b[j].b[i].y;" |
| << " g += s[i].b[j].b[0].x;" |
| << " b += s[i].b[j].b[1].x;" |
| << " a *= s[i].b[j].a;" |
| << " }" |
| << " }" |
| << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; }); |
| |
| LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform int ui_three;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[3];" |
| << " s[0] = S(${COORDS}.x, ui_zero);" |
| << " s[1].a = ${COORDS}.y;" |
| << " s[1].b = -ui_one;" |
| << " s[2] = S(${COORDS}.z, ui_two);" |
| << "" |
| << " mediump float rgb[3];" |
| << " int alpha = 0;" |
| << " for (int i = 0; i < ui_three; i++)" |
| << " {" |
| << " rgb[i] = s[2-i].a;" |
| << " alpha += s[i].b;" |
| << " }" |
| << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = c.coords.swizzle(2, 1, 0); }); |
| |
| LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform int ui_three;" |
| << "uniform mediump float uf_two;" |
| << "uniform mediump float uf_three;" |
| << "uniform mediump float uf_four;" |
| << "uniform mediump float uf_half;" |
| << "uniform mediump float uf_third;" |
| << "uniform mediump float uf_fourth;" |
| << "uniform mediump float uf_sixth;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " S s[2];" |
| << "" |
| << " // S[0]" |
| << " s[0].a = ${COORDS}.x;" |
| << " s[0].b[0].a = uf_half;" |
| << " s[0].b[0].b[0] = ${COORDS}.yx;" |
| << " s[0].b[0].b[1] = ${COORDS}.zx;" |
| << " s[0].b[1].a = uf_third;" |
| << " s[0].b[1].b[0] = ${COORDS}.yy;" |
| << " s[0].b[1].b[1] = ${COORDS}.wy;" |
| << " s[0].b[2].a = uf_fourth;" |
| << " s[0].b[2].b[0] = ${COORDS}.zx;" |
| << " s[0].b[2].b[1] = ${COORDS}.zy;" |
| << " s[0].c = ui_zero;" |
| << "" |
| << " // S[1]" |
| << " s[1].a = ${COORDS}.w;" |
| << " s[1].b[0].a = uf_two;" |
| << " s[1].b[0].b[0] = ${COORDS}.zx;" |
| << " s[1].b[0].b[1] = ${COORDS}.zy;" |
| << " s[1].b[1].a = uf_three;" |
| << " s[1].b[1].b[0] = ${COORDS}.zz;" |
| << " s[1].b[1].b[1] = ${COORDS}.ww;" |
| << " s[1].b[2].a = uf_four;" |
| << " s[1].b[2].b[0] = ${COORDS}.yx;" |
| << " s[1].b[2].b[1] = ${COORDS}.wz;" |
| << " s[1].c = ui_one;" |
| << "" |
| << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" |
| << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" |
| << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" |
| << " mediump float a = 1.0;" |
| << " for (int i = 0; i < ui_two; i++)" |
| << " {" |
| << " for (int j = 0; j < ui_three; j++)" |
| << " {" |
| << " r += s[0].b[j].b[i].y;" |
| << " g += s[i].b[j].b[0].x;" |
| << " b += s[i].b[j].b[1].x;" |
| << " a *= s[i].b[j].a;" |
| << " }" |
| << " }" |
| << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; }); |
| } |
| |
| class UniformStructTests : public TestCaseGroup |
| { |
| public: |
| UniformStructTests(Context& context, glu::GLSLVersion glslVersion) |
| : TestCaseGroup(context, "uniform", "Uniform structs"), m_glslVersion(glslVersion) |
| { |
| } |
| |
| ~UniformStructTests(void) |
| { |
| } |
| |
| virtual void init(void); |
| |
| private: |
| glu::GLSLVersion m_glslVersion; |
| }; |
| |
| namespace |
| { |
| |
| #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + NAME).c_str()) |
| |
| #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM) \ |
| void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \ |
| { \ |
| int loc = gl.getUniformLocation(programID, name); \ |
| SETUNIFORM(loc, 1, vec.getPtr()); \ |
| CHECK_SET_UNIFORM(name); \ |
| } \ |
| struct SetUniform##VECTYPE##Dummy_s \ |
| { \ |
| int unused; \ |
| } |
| |
| #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM) \ |
| void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE* vec, \ |
| int arraySize) \ |
| { \ |
| int loc = gl.getUniformLocation(programID, name); \ |
| SETUNIFORM(loc, arraySize, vec->getPtr()); \ |
| CHECK_SET_UNIFORM(name); \ |
| } \ |
| struct SetUniformPtr##VECTYPE##Dummy_s \ |
| { \ |
| int unused; \ |
| } |
| |
| MAKE_SET_VEC_UNIFORM(Vec2, gl.uniform2fv); |
| MAKE_SET_VEC_UNIFORM(Vec3, gl.uniform3fv); |
| MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv); |
| |
| void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, float value) |
| { |
| int loc = gl.getUniformLocation(programID, name); |
| gl.uniform1f(loc, value); |
| CHECK_SET_UNIFORM(name); |
| } |
| |
| void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, int value) |
| { |
| int loc = gl.getUniformLocation(programID, name); |
| gl.uniform1i(loc, value); |
| CHECK_SET_UNIFORM(name); |
| } |
| |
| void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize) |
| { |
| int loc = gl.getUniformLocation(programID, name); |
| gl.uniform1fv(loc, arraySize, value); |
| CHECK_SET_UNIFORM(name); |
| } |
| |
| } // anonymous |
| |
| void UniformStructTests::init(void) |
| { |
| #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \ |
| do \ |
| { \ |
| struct SetUniforms_##NAME \ |
| { \ |
| static void setUniforms(const glw::Functions& gl, deUint32 programID, \ |
| const tcu::Vec4& constCoords) SET_UNIFORMS_BODY \ |
| }; \ |
| struct Eval_##NAME \ |
| { \ |
| static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY \ |
| }; \ |
| addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, TEXTURES, \ |
| Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \ |
| addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, TEXTURES, \ |
| Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC)); \ |
| } while (deGetFalse()) |
| |
| UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " int c;" |
| << "};" |
| << "uniform S s;" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s.a", constCoords.x()); |
| setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3)); |
| setUniform(gl, programID, "s.c", 1); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); }); |
| |
| UNIFORM_STRUCT_CASE(nested, "Nested struct", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "" |
| << "struct T {" |
| << " int a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "uniform S s;" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s.a", constCoords.x()); |
| setUniform(gl, programID, "s.b.a", 0); |
| setUniform(gl, programID, "s.b.b", constCoords.swizzle(1, 2)); |
| setUniform(gl, programID, "s.c", 1); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); }); |
| |
| UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump float b[3];" |
| << " int c;" |
| << "};" |
| << "uniform S s;" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s.a", constCoords.w()); |
| setUniform(gl, programID, "s.c", 1); |
| |
| float b[3]; |
| b[0] = constCoords.z(); |
| b[1] = constCoords.y(); |
| b[2] = constCoords.x(); |
| setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b)); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(3, 2, 1); }); |
| |
| UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump float b[3];" |
| << " int c;" |
| << "};" |
| << "uniform S s;" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s.a", constCoords.w()); |
| setUniform(gl, programID, "s.c", 1); |
| |
| float b[3]; |
| b[0] = constCoords.z(); |
| b[1] = constCoords.y(); |
| b[2] = constCoords.x(); |
| setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b)); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(1, 2, 0); }); |
| |
| UNIFORM_STRUCT_CASE(struct_array, "Struct array", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "uniform S s[3];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| setUniform(gl, programID, "s[0].b", 0); |
| setUniform(gl, programID, "s[1].a", constCoords.y()); |
| setUniform(gl, programID, "s[1].b", 1); |
| setUniform(gl, programID, "s[2].a", constCoords.z()); |
| setUniform(gl, programID, "s[2].b", 2); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); |
| |
| UNIFORM_STRUCT_CASE( |
| struct_array_dynamic_index, "Struct array with dynamic indexing", false, |
| LineStream() |
| << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "uniform S s[3];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| setUniform(gl, programID, "s[0].b", 0); |
| setUniform(gl, programID, "s[1].a", constCoords.y()); |
| setUniform(gl, programID, "s[1].b", 1); |
| setUniform(gl, programID, "s[2].a", constCoords.z()); |
| setUniform(gl, programID, "s[2].b", 2); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); |
| |
| UNIFORM_STRUCT_CASE( |
| nested_struct_array, "Nested struct array", false, |
| LineStream() << "${HEADER}" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "uniform S s[2];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5" |
| << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" |
| << " mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w " |
| "+ w) * 0.333" |
| << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" |
| << " ${DST} = vec4(r, g, b, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| tcu::Vec2 arr[2]; |
| |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| arr[0] = constCoords.swizzle(0, 1); |
| arr[1] = constCoords.swizzle(2, 3); |
| setUniform(gl, programID, "s[0].b[0].a", 0.5f); |
| setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 3); |
| arr[1] = constCoords.swizzle(0, 1); |
| setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); |
| setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(0, 2); |
| arr[1] = constCoords.swizzle(1, 3); |
| setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); |
| setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[0].c", 0); |
| |
| setUniform(gl, programID, "s[1].a", constCoords.w()); |
| arr[0] = constCoords.swizzle(0, 0); |
| arr[1] = constCoords.swizzle(1, 1); |
| setUniform(gl, programID, "s[1].b[0].a", 2.0f); |
| setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 2); |
| arr[1] = constCoords.swizzle(3, 3); |
| setUniform(gl, programID, "s[1].b[1].a", 3.0f); |
| setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(1, 0); |
| arr[1] = constCoords.swizzle(3, 2); |
| setUniform(gl, programID, "s[1].b[2].a", 4.0f); |
| setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[1].c", 1); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); }); |
| |
| UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "uniform S s[2];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + " |
| "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5" |
| << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a " |
| "* s[ui_one].b[2].a; // x * 0.25 * 4" |
| << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + " |
| "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w " |
| "+ w + w) * 0.333" |
| << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - " |
| "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0" |
| << " ${DST} = vec4(r, g, b, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| tcu::Vec2 arr[2]; |
| |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| arr[0] = constCoords.swizzle(0, 1); |
| arr[1] = constCoords.swizzle(2, 3); |
| setUniform(gl, programID, "s[0].b[0].a", 0.5f); |
| setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 3); |
| arr[1] = constCoords.swizzle(0, 1); |
| setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); |
| setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(0, 2); |
| arr[1] = constCoords.swizzle(1, 3); |
| setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); |
| setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[0].c", 0); |
| |
| setUniform(gl, programID, "s[1].a", constCoords.w()); |
| arr[0] = constCoords.swizzle(0, 0); |
| arr[1] = constCoords.swizzle(1, 1); |
| setUniform(gl, programID, "s[1].b[0].a", 2.0f); |
| setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 2); |
| arr[1] = constCoords.swizzle(3, 3); |
| setUniform(gl, programID, "s[1].b[1].a", 3.0f); |
| setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(1, 0); |
| arr[1] = constCoords.swizzle(3, 2); |
| setUniform(gl, programID, "s[1].b[2].a", 4.0f); |
| setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[1].c", 1); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); }); |
| |
| UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "uniform S s[3];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " mediump float rgb[3];" |
| << " int alpha = 0;" |
| << " for (int i = 0; i < 3; i++)" |
| << " {" |
| << " rgb[i] = s[2-i].a;" |
| << " alpha += s[i].b;" |
| << " }" |
| << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| setUniform(gl, programID, "s[0].b", 0); |
| setUniform(gl, programID, "s[1].a", constCoords.y()); |
| setUniform(gl, programID, "s[1].b", -1); |
| setUniform(gl, programID, "s[2].a", constCoords.z()); |
| setUniform(gl, programID, "s[2].b", 2); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); |
| |
| UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform mediump float uf_two;" |
| << "uniform mediump float uf_three;" |
| << "uniform mediump float uf_four;" |
| << "uniform mediump float uf_half;" |
| << "uniform mediump float uf_third;" |
| << "uniform mediump float uf_fourth;" |
| << "uniform mediump float uf_sixth;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "uniform S s[2];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" |
| << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" |
| << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" |
| << " mediump float a = 1.0;" |
| << " for (int i = 0; i < 2; i++)" |
| << " {" |
| << " for (int j = 0; j < 3; j++)" |
| << " {" |
| << " r += s[0].b[j].b[i].y;" |
| << " g += s[i].b[j].b[0].x;" |
| << " b += s[i].b[j].b[1].x;" |
| << " a *= s[i].b[j].a;" |
| << " }" |
| << " }" |
| << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| tcu::Vec2 arr[2]; |
| |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| arr[0] = constCoords.swizzle(1, 0); |
| arr[1] = constCoords.swizzle(2, 0); |
| setUniform(gl, programID, "s[0].b[0].a", 0.5f); |
| setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(1, 1); |
| arr[1] = constCoords.swizzle(3, 1); |
| setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); |
| setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 1); |
| arr[1] = constCoords.swizzle(2, 1); |
| setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); |
| setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[0].c", 0); |
| |
| setUniform(gl, programID, "s[1].a", constCoords.w()); |
| arr[0] = constCoords.swizzle(2, 0); |
| arr[1] = constCoords.swizzle(2, 1); |
| setUniform(gl, programID, "s[1].b[0].a", 2.0f); |
| setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 2); |
| arr[1] = constCoords.swizzle(3, 3); |
| setUniform(gl, programID, "s[1].b[1].a", 3.0f); |
| setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(1, 0); |
| arr[1] = constCoords.swizzle(3, 2); |
| setUniform(gl, programID, "s[1].b[2].a", 4.0f); |
| setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[1].c", 1); |
| }, |
| { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; }); |
| |
| UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform int ui_three;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump int b;" |
| << "};" |
| << "uniform S s[3];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " mediump float rgb[3];" |
| << " int alpha = 0;" |
| << " for (int i = 0; i < ui_three; i++)" |
| << " {" |
| << " rgb[i] = s[2-i].a;" |
| << " alpha += s[i].b;" |
| << " }" |
| << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| setUniform(gl, programID, "s[0].b", 0); |
| setUniform(gl, programID, "s[1].a", constCoords.y()); |
| setUniform(gl, programID, "s[1].b", -1); |
| setUniform(gl, programID, "s[2].a", constCoords.z()); |
| setUniform(gl, programID, "s[2].b", 2); |
| }, |
| { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); }); |
| |
| UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "uniform int ui_two;" |
| << "uniform int ui_three;" |
| << "uniform mediump float uf_two;" |
| << "uniform mediump float uf_three;" |
| << "uniform mediump float uf_four;" |
| << "uniform mediump float uf_half;" |
| << "uniform mediump float uf_third;" |
| << "uniform mediump float uf_fourth;" |
| << "uniform mediump float uf_sixth;" |
| << "" |
| << "struct T {" |
| << " mediump float a;" |
| << " mediump vec2 b[2];" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b[3];" |
| << " int c;" |
| << "};" |
| << "uniform S s[2];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" |
| << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" |
| << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" |
| << " mediump float a = 1.0;" |
| << " for (int i = 0; i < ui_two; i++)" |
| << " {" |
| << " for (int j = 0; j < ui_three; j++)" |
| << " {" |
| << " r += s[0].b[j].b[i].y;" |
| << " g += s[i].b[j].b[0].x;" |
| << " b += s[i].b[j].b[1].x;" |
| << " a *= s[i].b[j].a;" |
| << " }" |
| << " }" |
| << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| tcu::Vec2 arr[2]; |
| |
| setUniform(gl, programID, "s[0].a", constCoords.x()); |
| arr[0] = constCoords.swizzle(1, 0); |
| arr[1] = constCoords.swizzle(2, 0); |
| setUniform(gl, programID, "s[0].b[0].a", 0.5f); |
| setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(1, 1); |
| arr[1] = constCoords.swizzle(3, 1); |
| setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f); |
| setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 1); |
| arr[1] = constCoords.swizzle(2, 1); |
| setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f); |
| setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[0].c", 0); |
| |
| setUniform(gl, programID, "s[1].a", constCoords.w()); |
| arr[0] = constCoords.swizzle(2, 0); |
| arr[1] = constCoords.swizzle(2, 1); |
| setUniform(gl, programID, "s[1].b[0].a", 2.0f); |
| setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(2, 2); |
| arr[1] = constCoords.swizzle(3, 3); |
| setUniform(gl, programID, "s[1].b[1].a", 3.0f); |
| setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| arr[0] = constCoords.swizzle(1, 0); |
| arr[1] = constCoords.swizzle(3, 2); |
| setUniform(gl, programID, "s[1].b[2].a", 4.0f); |
| setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr)); |
| setUniform(gl, programID, "s[1].c", 1); |
| }, |
| { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; }); |
| |
| UNIFORM_STRUCT_CASE( |
| sampler, "Sampler in struct", true, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " sampler2D c;" |
| << "};" |
| << "uniform S s;" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| DE_UNREF(constCoords); |
| setUniform(gl, programID, "s.a", 1.0f); |
| setUniform(gl, programID, "s.b", tcu::Vec3(0.75f, 0.75f, 0.1f)); |
| setUniform(gl, programID, "s.c", TEXTURE_GRADIENT); |
| }, |
| { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); }); |
| |
| UNIFORM_STRUCT_CASE( |
| sampler_nested, "Sampler in nested struct", true, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_zero;" |
| << "uniform int ui_one;" |
| << "" |
| << "struct T {" |
| << " sampler2D a;" |
| << " mediump vec2 b;" |
| << "};" |
| << "struct S {" |
| << " mediump float a;" |
| << " T b;" |
| << " int c;" |
| << "};" |
| << "uniform S s;" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| DE_UNREF(constCoords); |
| setUniform(gl, programID, "s.a", 0.1f); |
| setUniform(gl, programID, "s.b.a", TEXTURE_GRADIENT); |
| setUniform(gl, programID, "s.b.b", tcu::Vec2(0.75f, 0.75f)); |
| setUniform(gl, programID, "s.c", 1); |
| }, |
| { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); }); |
| |
| UNIFORM_STRUCT_CASE( |
| sampler_array, "Sampler in struct array", true, |
| LineStream() << "${HEADER}" |
| << "uniform int ui_one;" |
| << "" |
| << "struct S {" |
| << " mediump float a;" |
| << " mediump vec3 b;" |
| << " sampler2D c;" |
| << "};" |
| << "uniform S s[2];" |
| << "" |
| << "void main (void)" |
| << "{" |
| << " ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);" |
| << " ${ASSIGN_POS}" |
| << "}", |
| { |
| DE_UNREF(constCoords); |
| setUniform(gl, programID, "s[0].a", 1.0f); |
| setUniform(gl, programID, "s[0].b", tcu::Vec3(0.75f, 0.75f, 0.25f)); |
| setUniform(gl, programID, "s[0].c", 1); |
| setUniform(gl, programID, "s[1].a", 0.0f); |
| setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.1f)); |
| setUniform(gl, programID, "s[1].c", TEXTURE_GRADIENT); |
| }, |
| { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); }); |
| } |
| |
| ShaderStructTests::ShaderStructTests(Context& context, glu::GLSLVersion glslVersion) |
| : TestCaseGroup(context, "struct", "Struct Tests"), m_glslVersion(glslVersion) |
| { |
| } |
| |
| ShaderStructTests::~ShaderStructTests(void) |
| { |
| } |
| |
| void ShaderStructTests::init(void) |
| { |
| addChild(new LocalStructTests(m_context, m_glslVersion)); |
| addChild(new UniformStructTests(m_context, m_glslVersion)); |
| } |
| |
| } // deqp |