| // | |
| // 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 <array> | |
| #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<const std::string, 10> 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; | |
| } | |
| } | |
| } |