src/third_party/angle/src/tests/gl_tests/MultisampledRenderToTextureTest.cpp
// Draw, copy, rebind the attachment, clear then draw.  The initial draw will need to unresolve
// color.  The framebuffer attachment is temporary changed and then reset back to the original.
// This causes the framebuffer to be recreated on the following clear and draw.  The clear prevents
// the final draw from doing an unresolve.  In the Vulkan backend, mismatches in unresolve state
// between framebuffer and render pass will result in an ASSERT and a validation error (if ASSERT is
// removed).
Draw, copy, rebind the attachment, clear then draw.  The initial draw will need to unresolve
color.  The framebuffer attachment is temporary changed and then reset back to the original.
This causes the framebuffer to be recreated on the following clear and draw.  The clear prevents
the final draw from doing an unresolve.  In the Vulkan backend, mismatches in unresolve state
between framebuffer and render pass will result in an ASSERT and a validation error (if ASSERT is
removed).
Draw copy rebind the attachment clear then draw . The initial draw will need to unresolve color . The framebuffer attachment is temporary changed and then reset back to the original . This causes the framebuffer to be recreated on the following clear and draw . The clear prevents the final draw from doing an unresolve . In the Vulkan backend mismatches in unresolve state between framebuffer and render pass will result in an ASSERT and a validation error ( if ASSERT is removed ) .
TEST_P(MultisampledRenderToTextureES3Test, DrawCopyRebindAttachmentClearThenDraw)
{
    ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
    constexpr GLsizei kSize = 64;
    setupCopyTexProgram();
    GLFramebuffer fboMS;
    glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
    std::vector<GLColor> initialColorData(kSize * kSize, GLColor::black);
    GLTexture colorMS;
    glBindTexture(GL_TEXTURE_2D, colorMS);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                 initialColorData.data());
    glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                         colorMS, 0, 4);
    EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
    ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
    glUseProgram(drawColor);
    GLint colorUniformLocation =
        glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
    ASSERT_NE(colorUniformLocation, -1);
    glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
    drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
    ASSERT_GL_NO_ERROR();
    GLTexture texture;
    glBindTexture(GL_TEXTURE_2D, texture);
    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    GLTexture color;
    glBindTexture(GL_TEXTURE_2D, color);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
    EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, colorMS);
    glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                         colorMS, 0, 4);
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(drawColor);
    glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
    ASSERT_GL_NO_ERROR();
    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
    EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::cyan);
    EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::cyan);
    EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::cyan);
    ASSERT_GL_NO_ERROR();
    verifyResults(texture, GLColor::red, kSize, 0, 0, kSize, kSize);
    ASSERT_GL_NO_ERROR();
}
TEST_P ( MultisampledRenderToTextureES3Test , DrawCopyRebindAttachmentClearThenDraw ) { ANGLE_SKIP_TEST_IF ( ! EnsureGLExtensionEnabled ( " " ) ) ; constexpr GLsizei kSize = 64 ; setupCopyTexProgram ( ) ; GLFramebuffer fboMS ; glBindFramebuffer ( GL_FRAMEBUFFER , fboMS ) ; std :: vector < GLColor > initialColorData ( kSize * kSize , GLColor :: black ) ; GLTexture colorMS ; glBindTexture ( GL_TEXTURE_2D , colorMS ) ; glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , kSize , kSize , 0 , GL_RGBA , GL_UNSIGNED_BYTE , initialColorData . data ( ) ) ; glFramebufferTexture2DMultisampleEXT ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , colorMS , 0 , 4 ) ; EXPECT_GL_FRAMEBUFFER_COMPLETE ( GL_FRAMEBUFFER ) ; ANGLE_GL_PROGRAM ( drawColor , essl1_shaders :: vs :: Simple ( ) , essl1_shaders :: fs :: UniformColor ( ) ) ; glUseProgram ( drawColor ) ; GLint colorUniformLocation = glGetUniformLocation ( drawColor , angle :: essl1_shaders :: ColorUniform ( ) ) ; ASSERT_NE ( colorUniformLocation , -1 ) ; glUniform4f ( colorUniformLocation , 1.0f , 0.0f , 0.0f , 1.0f ) ; drawQuad ( drawColor , essl1_shaders :: PositionAttrib ( ) , 0.5f ) ; ASSERT_GL_NO_ERROR ( ) ; GLTexture texture ; glBindTexture ( GL_TEXTURE_2D , texture ) ; glCopyTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , 0 , 0 , kSize , kSize , 0 ) ; glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ; glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ; GLTexture color ; glBindTexture ( GL_TEXTURE_2D , color ) ; glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , kSize , kSize , 0 , GL_RGBA , GL_UNSIGNED_BYTE , nullptr ) ; glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , color , 0 ) ; EXPECT_GL_FRAMEBUFFER_COMPLETE ( GL_FRAMEBUFFER ) ; glClear ( GL_COLOR_BUFFER_BIT ) ; glBindTexture ( GL_TEXTURE_2D , colorMS ) ; glFramebufferTexture2DMultisampleEXT ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , colorMS , 0 , 4 ) ; glClearColor ( 0.0f , 1.0f , 0.0f , 1.0f ) ; glClear ( GL_COLOR_BUFFER_BIT ) ; glUseProgram ( drawColor ) ; glUniform4f ( colorUniformLocation , 0.0f , 0.0f , 1.0f , 1.0f ) ; glEnable ( GL_BLEND ) ; glBlendFunc ( GL_ONE , GL_ONE ) ; drawQuad ( drawColor , essl1_shaders :: PositionAttrib ( ) , 0.5f ) ; ASSERT_GL_NO_ERROR ( ) ; EXPECT_PIXEL_COLOR_EQ ( 0 , 0 , GLColor :: cyan ) ; EXPECT_PIXEL_COLOR_EQ ( kSize - 1 , 0 , GLColor :: cyan ) ; EXPECT_PIXEL_COLOR_EQ ( 0 , kSize - 1 , GLColor :: cyan ) ; EXPECT_PIXEL_COLOR_EQ ( kSize - 1 , kSize - 1 , GLColor :: cyan ) ; ASSERT_GL_NO_ERROR ( ) ; verifyResults ( texture , GLColor :: red , kSize , 0 , 0 , kSize , kSize ) ; ASSERT_GL_NO_ERROR ( ) ; }
Draw, copy, rebind the attachment, clear then draw.
Draw copy rebind the attachment clear then draw .
// Create multisampled framebuffer to draw into // Draw red into the multisampled color buffer. // Draw into framebuffer.  This will unresolve color. // Create a texture and copy into it. // Bind the framebuffer to another texture. // Do whatever. // Rebind the framebuffer back to the original texture. // Clear to green and blend blue into the multisampled color buffer. // Verify that the texture is now cyan // For completeness, verify that the texture used as copy target is red.