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