// // Copyright 2018 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // TextureFunction_test.cpp: // Tests that malformed texture function calls don't pass compilation. // #include #include "GLSLANG/ShaderLang.h" #include "angle_gl.h" #include "gtest/gtest.h" #include "tests/test_utils/ShaderCompileTreeTest.h" using namespace sh; class TextureFunctionTest : public ShaderCompileTreeTest { public: TextureFunctionTest() {} protected: ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } }; // Test that none of the texture offset functions can take a non-constant parameter. TEST_F(TextureFunctionTest, NonConstantOffset) { const std::string &shaderTemplate = R"(#version 310 es precision mediump float; out vec4 my_FragColor; uniform sampler2D s; uniform vec4 samplePos; void main() { my_FragColor = {sample}; })"; const std::array sampleVariants( {"texelFetchOffset(s, ivec2(samplePos.xy), 0, {offset})", "textureLodOffset(s, samplePos.xy, 0.0, {offset})", "textureProjLodOffset(s, samplePos.xyz, 0.0, {offset})", "textureGradOffset(s, samplePos.xy, vec2(1.0), vec2(1.0), {offset})", "textureProjGradOffset(s, samplePos.xyz, vec2(1.0), vec2(1.0), {offset})", "textureOffset(s, samplePos.xy, {offset})", "textureOffset(s, samplePos.xy, {offset}, 1.0)", "textureProjOffset(s, samplePos.xyz, {offset})", "textureProjOffset(s, samplePos.xyz, {offset}, 1.0)", "textureGatherOffset(s, samplePos.xy, {offset})"}); size_t sampleReplacePos = shaderTemplate.find("{sample}"); for (auto &variantTemplate : sampleVariants) { size_t offsetReplacePos = variantTemplate.find("{offset}"); std::string variantConst = variantTemplate; variantConst.replace(offsetReplacePos, 8, "ivec2(0, 0)"); std::string shaderValid = shaderTemplate; shaderValid.replace(sampleReplacePos, 8, variantConst); if (!compile(shaderValid)) { FAIL() << "Shader compilation failed with sample function " << variantConst << ", expecting success:\n" << mInfoLog; } std::string variantNonConst = variantTemplate; variantNonConst.replace(offsetReplacePos, 8, "ivec2(samplePos.xy)"); std::string shaderNonConst = shaderTemplate; shaderNonConst.replace(sampleReplacePos, 8, variantNonConst); if (compile(shaderNonConst)) { FAIL() << "Shader compilation succeeded with sample function " << variantNonConst << ", expecting failure:\n" << mInfoLog; } std::string variantOutOfBounds = variantTemplate; variantOutOfBounds.replace(offsetReplacePos, 8, "ivec2(1000, 1000)"); std::string shaderOutOfBounds = shaderTemplate; shaderOutOfBounds.replace(sampleReplacePos, 8, variantOutOfBounds); if (compile(shaderOutOfBounds)) { FAIL() << "Shader compilation succeeded with sample function " << variantOutOfBounds << ", expecting failure:\n" << mInfoLog; } } }