Path: blob/main_old/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56#include "test_utils/ANGLETest.h"7#include "test_utils/gl_raii.h"89using namespace angle;1011class DiscardFramebufferEXTTest : public ANGLETest12{13protected:14DiscardFramebufferEXTTest()15{16setWindowWidth(256);17setWindowHeight(256);18setConfigRedBits(8);19setConfigGreenBits(8);20setConfigBlueBits(8);21setConfigAlphaBits(8);22setConfigDepthBits(24);23setConfigStencilBits(8);24}25};2627TEST_P(DiscardFramebufferEXTTest, DefaultFramebuffer)28{29ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_discard_framebuffer"));3031// TODO: fix crash issue. http://anglebug.com/414132ANGLE_SKIP_TEST_IF(IsD3D11());3334// These should succeed on the default framebuffer35const GLenum discards1[] = {GL_COLOR_EXT};36glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards1);37EXPECT_GL_NO_ERROR();3839const GLenum discards2[] = {GL_DEPTH_EXT};40glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards2);41EXPECT_GL_NO_ERROR();4243const GLenum discards3[] = {GL_STENCIL_EXT};44glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards3);45EXPECT_GL_NO_ERROR();4647const GLenum discards4[] = {GL_STENCIL_EXT, GL_COLOR_EXT, GL_DEPTH_EXT};48glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, discards4);49EXPECT_GL_NO_ERROR();5051// These should fail on the default framebuffer52const GLenum discards5[] = {GL_COLOR_ATTACHMENT0};53glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards5);54EXPECT_GL_ERROR(GL_INVALID_ENUM);5556const GLenum discards6[] = {GL_DEPTH_ATTACHMENT};57glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards6);58EXPECT_GL_ERROR(GL_INVALID_ENUM);5960const GLenum discards7[] = {GL_STENCIL_ATTACHMENT};61glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards7);62EXPECT_GL_ERROR(GL_INVALID_ENUM);63}6465TEST_P(DiscardFramebufferEXTTest, NonDefaultFramebuffer)66{67ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_discard_framebuffer"));6869GLuint tex2D;70GLuint framebuffer;7172// Create a basic off-screen framebuffer73// Don't create a depth/stencil texture, to ensure that also works correctly74glGenTextures(1, &tex2D);75glGenFramebuffers(1, &framebuffer);76glBindTexture(GL_TEXTURE_2D, tex2D);77glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);78glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,79GL_UNSIGNED_BYTE, nullptr);80glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);81glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);82glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 0);83ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));8485// These should fail on the non-default framebuffer86const GLenum discards1[] = {GL_COLOR_EXT};87glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards1);88EXPECT_GL_ERROR(GL_INVALID_ENUM);8990const GLenum discards2[] = {GL_DEPTH_EXT};91glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards2);92EXPECT_GL_ERROR(GL_INVALID_ENUM);9394const GLenum discards3[] = {GL_STENCIL_EXT};95glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards3);96EXPECT_GL_ERROR(GL_INVALID_ENUM);9798const GLenum discards4[] = {GL_STENCIL_EXT, GL_COLOR_EXT, GL_DEPTH_EXT};99glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, discards4);100EXPECT_GL_ERROR(GL_INVALID_ENUM);101102// These should succeed on the non-default framebuffer103const GLenum discards5[] = {GL_COLOR_ATTACHMENT0};104glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards5);105EXPECT_GL_NO_ERROR();106107const GLenum discards6[] = {GL_DEPTH_ATTACHMENT};108glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards6);109EXPECT_GL_NO_ERROR();110111const GLenum discards7[] = {GL_STENCIL_ATTACHMENT};112glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards7);113EXPECT_GL_NO_ERROR();114}115116// ANGLE implements an optimization that if depth stencil buffer has not been used and not stored in117// the renderpass, the depth buffer clear will be dropped.118TEST_P(DiscardFramebufferEXTTest, ClearDepthThenDrawWithoutDepthTestThenDiscard)119{120ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_discard_framebuffer"));121// TODO: fix crash issue. http://anglebug.com/4141122ANGLE_SKIP_TEST_IF(IsD3D11());123124ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());125glUseProgram(program);126GLint colorUniformLocation =127glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());128ASSERT_NE(-1, colorUniformLocation);129ASSERT_GL_NO_ERROR();130131constexpr GLfloat kDepthClearValue = 0.5f;132// This depth value equals to kDepthClearValue after viewport transform133constexpr GLfloat depthDrawValue = kDepthClearValue * 2.0f - 1.0f;134135// This depth clear should be optimized out. We do not have a good way to verify that it136// actually gets dropped, but at least we will ensure rendering is still correct.137glBindFramebuffer(GL_FRAMEBUFFER, 0);138glEnable(GL_DEPTH_TEST);139glClearDepthf(kDepthClearValue);140glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);141glDisable(GL_DEPTH_TEST);142glUniform4fv(colorUniformLocation, 1, GLColor::cyan.toNormalizedVector().data());143glViewport(0, 0, getWindowWidth(), getWindowHeight());144drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue + 0.05f);145GLenum discards = GL_DEPTH_EXT;146glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &discards);147ASSERT_GL_NO_ERROR();148EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::cyan);149}150151// This test is try to ensure that if depth test has been used, depth clear does not get optimized152// out. It also tests that if the depth buffer has not been used, the rendering is still correct.153TEST_P(DiscardFramebufferEXTTest, ClearDepthThenDrawWithDepthTestThenDiscard)154{155ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_discard_framebuffer"));156// http://anglebug.com/4914157ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());158159GLTexture texture;160GLRenderbuffer renderbuffer;161GLFramebuffer framebuffer;162GLint colorUniformLocation;163constexpr GLsizei kTexWidth = 256;164constexpr GLsizei kTexHeight = 256;165166glBindTexture(GL_TEXTURE_2D, texture);167glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kTexWidth, kTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,168nullptr);169glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);170glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);171ASSERT_GL_NO_ERROR();172glBindTexture(GL_TEXTURE_2D, 0);173174glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);175glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kTexWidth, kTexWidth);176glBindRenderbuffer(GL_RENDERBUFFER, 0);177ASSERT_GL_NO_ERROR();178179glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);180glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);181glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);182ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));183ASSERT_GL_NO_ERROR();184185ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());186glUseProgram(program);187colorUniformLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());188ASSERT_NE(-1, colorUniformLocation);189ASSERT_GL_NO_ERROR();190191// Draw into FBO0192glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);193glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // clear to green194constexpr GLfloat kDepthClearValue = 0.5f;195// This depth value equals to kDepthClearValue after viewport transform196constexpr GLfloat depthDrawValue = kDepthClearValue * 2.0f - 1.0f;197glClearDepthf(kDepthClearValue);198glEnable(GL_DEPTH_TEST);199glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);200// Draw bottom left with depth test disabled. DepthValue should remain 0.5f with blue color.201glDepthFunc(GL_LESS);202glDisable(GL_DEPTH_TEST);203glViewport(0, 0, kTexWidth / 2, kTexHeight / 2);204glUniform4fv(colorUniformLocation, 1, GLColor::blue.toNormalizedVector().data());205drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue - 0.1f);206// Draw bottom right with depth test enabled. DepthValue should be 0.45f with blue color.207glEnable(GL_DEPTH_TEST);208glViewport(kTexWidth / 2, 0, kTexWidth / 2, kTexHeight / 2);209drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue - 0.1f);210// Draw to top left with depth test disabled. DepthValue should remain 0.5f with blue color211glDisable(GL_DEPTH_TEST);212glViewport(0, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2);213drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue + 0.1f);214// Draw to top right with depth test enabled. DepthValue should remain 0.5f with green color215glEnable(GL_DEPTH_TEST);216glViewport(kTexWidth / 2, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2);217drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue + 0.1f);218219// Now draw the full quad with depth test enabled to verify the depth value is expected.220// It should fail depth test in bottom right which will keep it with blue color. All other221// quarters will pass depth test and draw a red quad.222glEnable(GL_DEPTH_TEST);223glUniform4fv(colorUniformLocation, 1, GLColor::red.toNormalizedVector().data());224glViewport(0, 0, kTexWidth, kTexHeight);225drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue - 0.05f);226227// Invalidate depth buffer. This will trigger depth value not been written to buffer but the228// depth load/clear should not optimize out229GLenum discards = GL_DEPTH_ATTACHMENT;230glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &discards);231ASSERT_GL_NO_ERROR();232233EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);234EXPECT_PIXEL_COLOR_EQ(kTexWidth / 2 + 1, 1, GLColor::blue);235EXPECT_PIXEL_COLOR_EQ(1, kTexHeight / 2 + 1, GLColor::red);236EXPECT_PIXEL_COLOR_EQ(kTexWidth / 2 + 1, kTexHeight / 2 + 1, GLColor::red);237}238239// Use this to select which configurations (e.g. which renderer, which GLES major version) these240// tests should be run against.241ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DiscardFramebufferEXTTest);242243244