1 //
2 // Copyright 2020 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 // ContextNoErrorTest:
7 // Tests pertaining to GL_KHR_no_error
8 //
9
10 #include <gtest/gtest.h>
11
12 #include "common/platform.h"
13 #include "test_utils/ANGLETest.h"
14 #include "test_utils/gl_raii.h"
15
16 using namespace angle;
17
18 class ContextNoErrorTest : public ANGLETest
19 {
20 protected:
ContextNoErrorTest()21 ContextNoErrorTest() : mNaughtyTexture(0) { setNoErrorEnabled(true); }
22
testTearDown()23 void testTearDown() override
24 {
25 if (mNaughtyTexture != 0)
26 {
27 glDeleteTextures(1, &mNaughtyTexture);
28 }
29 }
30
bindNaughtyTexture()31 void bindNaughtyTexture()
32 {
33 glGenTextures(1, &mNaughtyTexture);
34 ASSERT_GL_NO_ERROR();
35 glBindTexture(GL_TEXTURE_CUBE_MAP, mNaughtyTexture);
36 ASSERT_GL_NO_ERROR();
37
38 // mNaughtyTexture should now be a GL_TEXTURE_CUBE_MAP texture, so rebinding it to
39 // GL_TEXTURE_2D is an error
40 glBindTexture(GL_TEXTURE_2D, mNaughtyTexture);
41 }
42
43 GLuint mNaughtyTexture;
44 };
45
46 class ContextNoErrorTest31 : public ContextNoErrorTest
47 {
48 protected:
~ContextNoErrorTest31()49 ~ContextNoErrorTest31()
50 {
51 glDeleteProgram(mVertProg);
52 glDeleteProgram(mFragProg);
53 glDeleteProgramPipelines(1, &mPipeline);
54 }
55
56 void bindProgramPipeline(const GLchar *vertString, const GLchar *fragString);
57 void drawQuadWithPPO(const std::string &positionAttribName,
58 const GLfloat positionAttribZ,
59 const GLfloat positionAttribXYScale);
60
61 GLuint mVertProg;
62 GLuint mFragProg;
63 GLuint mPipeline;
64 };
65
bindProgramPipeline(const GLchar * vertString,const GLchar * fragString)66 void ContextNoErrorTest31::bindProgramPipeline(const GLchar *vertString, const GLchar *fragString)
67 {
68 mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
69 ASSERT_NE(mVertProg, 0u);
70 mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
71 ASSERT_NE(mFragProg, 0u);
72
73 // Generate a program pipeline and attach the programs to their respective stages
74 glGenProgramPipelines(1, &mPipeline);
75 EXPECT_GL_NO_ERROR();
76 glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
77 EXPECT_GL_NO_ERROR();
78 glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
79 EXPECT_GL_NO_ERROR();
80 glBindProgramPipeline(mPipeline);
81 EXPECT_GL_NO_ERROR();
82 }
83
drawQuadWithPPO(const std::string & positionAttribName,const GLfloat positionAttribZ,const GLfloat positionAttribXYScale)84 void ContextNoErrorTest31::drawQuadWithPPO(const std::string &positionAttribName,
85 const GLfloat positionAttribZ,
86 const GLfloat positionAttribXYScale)
87 {
88 glUseProgram(0);
89
90 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
91
92 for (Vector3 &vertex : quadVertices)
93 {
94 vertex.x() *= positionAttribXYScale;
95 vertex.y() *= positionAttribXYScale;
96 vertex.z() = positionAttribZ;
97 }
98
99 GLint positionLocation = glGetAttribLocation(mVertProg, positionAttribName.c_str());
100
101 glBindBuffer(GL_ARRAY_BUFFER, 0);
102 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
103 glEnableVertexAttribArray(positionLocation);
104
105 glDrawArrays(GL_TRIANGLES, 0, 6);
106
107 glDisableVertexAttribArray(positionLocation);
108 glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
109 }
110
111 // Tests that error reporting is suppressed when GL_KHR_no_error is enabled
TEST_P(ContextNoErrorTest,NoError)112 TEST_P(ContextNoErrorTest, NoError)
113 {
114 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error"));
115
116 bindNaughtyTexture();
117 EXPECT_GL_NO_ERROR();
118 }
119
120 // Test glDetachShader to make sure it resolves linking with a no error context and doesn't assert
TEST_P(ContextNoErrorTest,DetachAfterLink)121 TEST_P(ContextNoErrorTest, DetachAfterLink)
122 {
123 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error"));
124
125 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
126 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
127 GLuint program = glCreateProgram();
128 glAttachShader(program, vs);
129 glAttachShader(program, fs);
130 glLinkProgram(program);
131
132 glDetachShader(program, vs);
133 glDetachShader(program, fs);
134
135 glDeleteShader(vs);
136 glDeleteShader(fs);
137 glDeleteProgram(program);
138 EXPECT_GL_NO_ERROR();
139 }
140
141 // Tests that we can draw with a program pipeline when GL_KHR_no_error is enabled.
TEST_P(ContextNoErrorTest31,DrawWithPPO)142 TEST_P(ContextNoErrorTest31, DrawWithPPO)
143 {
144 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error"));
145
146 // Only the Vulkan backend supports PPOs
147 ANGLE_SKIP_TEST_IF(!IsVulkan());
148
149 // TODO(http://anglebug.com/5102): Linking PPOs is currently done during draw call validation,
150 // so drawing with a PPO fails without validation enabled.
151 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_no_error"));
152
153 // Create two separable program objects from a
154 // single source string respectively (vertSrc and fragSrc)
155 const GLchar *vertString = essl31_shaders::vs::Simple();
156 const GLchar *fragString = essl31_shaders::fs::Red();
157
158 bindProgramPipeline(vertString, fragString);
159
160 drawQuadWithPPO("a_position", 0.5f, 1.0f);
161 ASSERT_GL_NO_ERROR();
162 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
163 }
164
165 // Tests that an incorrect enum to GetInteger does not cause an application crash.
TEST_P(ContextNoErrorTest,InvalidGetIntegerDoesNotCrash)166 TEST_P(ContextNoErrorTest, InvalidGetIntegerDoesNotCrash)
167 {
168 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error"));
169
170 GLint value = 1;
171 glGetIntegerv(GL_TEXTURE_2D, &value);
172 EXPECT_GL_NO_ERROR();
173 EXPECT_EQ(value, 1);
174 }
175
176 // Test that we ignore an invalid texture type when EGL_KHR_create_context_no_error is enabled.
TEST_P(ContextNoErrorTest,InvalidTextureType)177 TEST_P(ContextNoErrorTest, InvalidTextureType)
178 {
179 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_no_error"));
180
181 GLTexture texture;
182 constexpr GLenum kInvalidTextureType = 0;
183
184 glBindTexture(kInvalidTextureType, texture);
185 ASSERT_GL_NO_ERROR();
186
187 glTexParameteri(kInvalidTextureType, GL_TEXTURE_BASE_LEVEL, 0);
188 ASSERT_GL_NO_ERROR();
189 }
190
191 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ContextNoErrorTest);
192
193 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextNoErrorTest31);
194 ANGLE_INSTANTIATE_TEST_ES31(ContextNoErrorTest31);
195