1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // TextureFunction_test.cpp:
7 // Tests that malformed texture function calls don't pass compilation.
8 //
9
10 #include <array>
11
12 #include "GLSLANG/ShaderLang.h"
13 #include "angle_gl.h"
14 #include "gtest/gtest.h"
15 #include "tests/test_utils/ShaderCompileTreeTest.h"
16
17 using namespace sh;
18
19 class TextureFunctionTest : public ShaderCompileTreeTest
20 {
21 public:
TextureFunctionTest()22 TextureFunctionTest() {}
23
24 protected:
getShaderType() const25 ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
getShaderSpec() const26 ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
27 };
28
29 // Test that none of the texture offset functions can take a non-constant parameter.
TEST_F(TextureFunctionTest,NonConstantOffset)30 TEST_F(TextureFunctionTest, NonConstantOffset)
31 {
32 const std::string &shaderTemplate =
33 R"(#version 310 es
34 precision mediump float;
35 out vec4 my_FragColor;
36 uniform sampler2D s;
37 uniform vec4 samplePos;
38
39 void main()
40 {
41 my_FragColor = {sample};
42 })";
43
44 const std::array<const std::string, 10> sampleVariants(
45 {"texelFetchOffset(s, ivec2(samplePos.xy), 0, {offset})",
46 "textureLodOffset(s, samplePos.xy, 0.0, {offset})",
47 "textureProjLodOffset(s, samplePos.xyz, 0.0, {offset})",
48 "textureGradOffset(s, samplePos.xy, vec2(1.0), vec2(1.0), {offset})",
49 "textureProjGradOffset(s, samplePos.xyz, vec2(1.0), vec2(1.0), {offset})",
50 "textureOffset(s, samplePos.xy, {offset})",
51 "textureOffset(s, samplePos.xy, {offset}, 1.0)",
52 "textureProjOffset(s, samplePos.xyz, {offset})",
53 "textureProjOffset(s, samplePos.xyz, {offset}, 1.0)",
54 "textureGatherOffset(s, samplePos.xy, {offset})"});
55
56 size_t sampleReplacePos = shaderTemplate.find("{sample}");
57
58 for (auto &variantTemplate : sampleVariants)
59 {
60 size_t offsetReplacePos = variantTemplate.find("{offset}");
61
62 std::string variantConst = variantTemplate;
63 variantConst.replace(offsetReplacePos, 8, "ivec2(0, 0)");
64
65 std::string shaderValid = shaderTemplate;
66 shaderValid.replace(sampleReplacePos, 8, variantConst);
67 if (!compile(shaderValid))
68 {
69 FAIL() << "Shader compilation failed with sample function " << variantConst
70 << ", expecting success:\n"
71 << mInfoLog;
72 }
73
74 std::string variantNonConst = variantTemplate;
75 variantNonConst.replace(offsetReplacePos, 8, "ivec2(samplePos.xy)");
76
77 std::string shaderNonConst = shaderTemplate;
78 shaderNonConst.replace(sampleReplacePos, 8, variantNonConst);
79 if (compile(shaderNonConst))
80 {
81 FAIL() << "Shader compilation succeeded with sample function " << variantNonConst
82 << ", expecting failure:\n"
83 << mInfoLog;
84 }
85
86 std::string variantOutOfBounds = variantTemplate;
87 variantOutOfBounds.replace(offsetReplacePos, 8, "ivec2(1000, 1000)");
88
89 std::string shaderOutOfBounds = shaderTemplate;
90 shaderOutOfBounds.replace(sampleReplacePos, 8, variantOutOfBounds);
91 if (compile(shaderOutOfBounds))
92 {
93 FAIL() << "Shader compilation succeeded with sample function " << variantOutOfBounds
94 << ", expecting failure:\n"
95 << mInfoLog;
96 }
97 }
98 }
99