@@ -101,6 +101,7 @@ class MultisampledRenderToTextureTest : public ANGLETest
101101 glDisable (GL_DEPTH_TEST);
102102 glDisable (GL_STENCIL_TEST);
103103 glDisable (GL_BLEND);
104+ glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
104105 drawQuad (mCopyTextureProgram , essl1_shaders::PositionAttrib (), 0 .5f );
105106
106107 // Expect that the rendered quad has the same color as the source texture
@@ -144,6 +145,7 @@ class MultisampledRenderToTextureTest : public ANGLETest
144145 void copyTexSubImageTestCommon (bool useRenderbuffer);
145146 void drawCopyThenBlendCommon (bool useRenderbuffer);
146147 void clearDrawCopyThenBlendSameProgramCommon (bool useRenderbuffer);
148+ void drawCopyDrawThenMaskedClearCommon (bool useRenderbuffer);
147149 void clearThenBlendCommon (bool useRenderbuffer);
148150
149151 GLProgram mCopyTextureProgram ;
@@ -1066,6 +1068,14 @@ void MultisampledRenderToTextureTest::clearDrawCopyThenBlendSameProgramCommon(bo
10661068 drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
10671069 ASSERT_GL_NO_ERROR ();
10681070
1071+ // Blend green into it. This makes sure that the blend after the resolve doesn't have different
1072+ // state from the one used here.
1073+ glEnable (GL_BLEND);
1074+ glBlendFunc (GL_ONE, GL_ONE);
1075+ glUniform4f (colorUniformLocation, 0 .0f , 1 .0f , 0 .0f , 1 .0f );
1076+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
1077+ ASSERT_GL_NO_ERROR ();
1078+
10691079 // Create a texture and copy into it.
10701080 GLTexture texture;
10711081 glBindTexture (GL_TEXTURE_2D, texture);
@@ -1077,35 +1087,31 @@ void MultisampledRenderToTextureTest::clearDrawCopyThenBlendSameProgramCommon(bo
10771087 // residing in the single-sampled texture, is available to the multisampled intermediate image
10781088 // for blending.
10791089
1080- // Blend half-transparent green into the multisampled color buffer.
1081- glUniform4f (colorUniformLocation, 0 .0f , 1 .0f , 0 .0f , 0 .5f );
1082- glEnable (GL_BLEND);
1083- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1090+ // Blend blue into the multisampled color buffer.
1091+ glUniform4f (colorUniformLocation, 0 .0f , 0 .0f , 1 .0f , 1 .0f );
10841092 drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
10851093 ASSERT_GL_NO_ERROR ();
10861094
1087- // Verify that the texture is now yellow
1088- const GLColor kExpected (127 , 127 , 0 , 191 );
1089- EXPECT_PIXEL_COLOR_NEAR (0 , 0 , kExpected , 1 );
1090- EXPECT_PIXEL_COLOR_NEAR (kSize - 1 , 0 , kExpected , 1 );
1091- EXPECT_PIXEL_COLOR_NEAR (0 , kSize - 1 , kExpected , 1 );
1092- EXPECT_PIXEL_COLOR_NEAR (kSize - 1 , kSize - 1 , kExpected , 1 );
1095+ // Verify that the texture is now white
1096+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::white);
1097+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , 0 , GLColor::white);
1098+ EXPECT_PIXEL_COLOR_EQ (0 , kSize - 1 , GLColor::white);
1099+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , kSize - 1 , GLColor::white);
10931100
10941101 // Once again, clear and draw so the program is used again in the way it was first used.
10951102 glClear (GL_COLOR_BUFFER_BIT);
10961103 glDisable (GL_BLEND);
10971104 glUniform4f (colorUniformLocation, 0 .0f , 0 .0f , 1 .0f , 1 .0f );
10981105 drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
10991106
1100- EXPECT_PIXEL_COLOR_NEAR (0 , 0 , GLColor::blue, 1 );
1101- EXPECT_PIXEL_COLOR_NEAR (kSize - 1 , 0 , GLColor::blue, 1 );
1102- EXPECT_PIXEL_COLOR_NEAR (0 , kSize - 1 , GLColor::blue, 1 );
1103- EXPECT_PIXEL_COLOR_NEAR (kSize - 1 , kSize - 1 , GLColor::blue, 1 );
1107+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::blue);
1108+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , 0 , GLColor::blue);
1109+ EXPECT_PIXEL_COLOR_EQ (0 , kSize - 1 , GLColor::blue);
1110+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , kSize - 1 , GLColor::blue);
11041111
1105- // For completeness, verify that the texture used as copy target is red .
1112+ // For completeness, verify that the texture used as copy target is yellow .
11061113 ASSERT_GL_NO_ERROR ();
1107- const GLColor kExpectedCopyResult (255 , 0 , 0 , 255 );
1108- verifyResults (texture, kExpectedCopyResult , kSize , 0 , 0 , kSize , kSize );
1114+ verifyResults (texture, GLColor::yellow, kSize , 0 , 0 , kSize , kSize );
11091115
11101116 ASSERT_GL_NO_ERROR ();
11111117}
@@ -1126,6 +1132,200 @@ TEST_P(MultisampledRenderToTextureTest, RenderbufferClearDrawCopyThenBlendSamePr
11261132 clearDrawCopyThenBlendSameProgramCommon (true );
11271133}
11281134
1135+ // Similar to RenderbufferClearDrawCopyThenBlendSameProgram, but with the depth/stencil attachment
1136+ // being unresolved only.
1137+ TEST_P (MultisampledRenderToTextureES3Test,
1138+ RenderbufferClearDrawCopyThenBlendWithDepthStencilSameProgram)
1139+ {
1140+ ANGLE_SKIP_TEST_IF (!EnsureGLExtensionEnabled (" GL_EXT_multisampled_render_to_texture" ));
1141+ constexpr GLsizei kSize = 64 ;
1142+
1143+ setupCopyTexProgram ();
1144+
1145+ GLFramebuffer fboMS;
1146+ glBindFramebuffer (GL_FRAMEBUFFER, fboMS);
1147+
1148+ // Create multisampled framebuffer to draw into
1149+ GLTexture color;
1150+ glBindTexture (GL_TEXTURE_2D, color);
1151+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, kSize , kSize , 0 , GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
1152+ glFramebufferTexture2DMultisampleEXT (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
1153+ 0 , 4 );
1154+
1155+ GLRenderbuffer depthStencil;
1156+ glBindRenderbuffer (GL_RENDERBUFFER, depthStencil);
1157+ glRenderbufferStorageMultisampleEXT (GL_RENDERBUFFER, 4 , GL_DEPTH24_STENCIL8, kSize , kSize );
1158+ glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1159+ depthStencil);
1160+ ASSERT_GL_NO_ERROR ();
1161+ EXPECT_GL_FRAMEBUFFER_COMPLETE (GL_FRAMEBUFFER);
1162+
1163+ // Draw red into the multisampled color buffer.
1164+ ANGLE_GL_PROGRAM (drawColor, essl1_shaders::vs::Simple (), essl1_shaders::fs::UniformColor ());
1165+ glUseProgram (drawColor);
1166+ GLint colorUniformLocation =
1167+ glGetUniformLocation (drawColor, angle::essl1_shaders::ColorUniform ());
1168+ ASSERT_NE (colorUniformLocation, -1 );
1169+
1170+ // Enable write to depth/stencil so the attachment has valid contents, but always pass the test.
1171+ glEnable (GL_DEPTH_TEST);
1172+ glDepthFunc (GL_ALWAYS);
1173+
1174+ glEnable (GL_STENCIL_TEST);
1175+ glStencilFunc (GL_ALWAYS, 0x55 , 0xFF );
1176+ glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
1177+ glStencilMask (0xFF );
1178+
1179+ // Clear the framebuffer.
1180+ glClearColor (0 .1f , 0 .9f , 0 .2f , 0 .8f );
1181+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1182+
1183+ // Then draw into it.
1184+ glUniform4f (colorUniformLocation, 1 .0f , 0 .0f , 0 .0f , 1 .0f );
1185+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 1 .0f );
1186+ ASSERT_GL_NO_ERROR ();
1187+
1188+ // Blend green into it. This makes sure that the blend after the resolve doesn't have different
1189+ // state from the one used here. Additionally, test that the previous draw output the correct
1190+ // depth/stencil data. Again, this makes sure that the draw call after the resolve doesn't have
1191+ // different has depth/stencil test state.
1192+
1193+ // If depth is not set to 1, rendering would fail.
1194+ glDepthFunc (GL_LESS);
1195+
1196+ // If stencil is not set to 0x55, rendering would fail.
1197+ glStencilFunc (GL_EQUAL, 0x55 , 0xFF );
1198+ glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
1199+
1200+ glEnable (GL_BLEND);
1201+ glBlendFunc (GL_ONE, GL_ONE);
1202+ glUniform4f (colorUniformLocation, 0 .0f , 1 .0f , 0 .0f , 1 .0f );
1203+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .95f );
1204+ ASSERT_GL_NO_ERROR ();
1205+
1206+ // Create a texture and copy into it.
1207+ GLTexture texture;
1208+ glBindTexture (GL_TEXTURE_2D, texture);
1209+ glCopyTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, 0 , 0 , kSize , kSize , 0 );
1210+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1211+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1212+
1213+ // Clear color (but not depth/stencil), and draw again into the framebuffer, this time blending.
1214+ // Additionally, make sure the depth/stencil data are retained.
1215+
1216+ // Clear color (to blue), but not depth/stencil.
1217+ glClearColor (0 .0f , 0 .0f , 1 .0f , 1 .0f );
1218+ glClear (GL_COLOR_BUFFER_BIT);
1219+
1220+ // Blend green into the multisampled color buffer.
1221+ glUniform4f (colorUniformLocation, 0 .0f , 1 .0f , 0 .0f , 1 .0f );
1222+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .9f );
1223+ ASSERT_GL_NO_ERROR ();
1224+
1225+ // Verify that the texture is now cyan
1226+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::cyan);
1227+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , 0 , GLColor::cyan);
1228+ EXPECT_PIXEL_COLOR_EQ (0 , kSize - 1 , GLColor::cyan);
1229+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , kSize - 1 , GLColor::cyan);
1230+
1231+ // Once again, clear and draw so the program is used again in the way it was first used.
1232+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1233+ glDisable (GL_BLEND);
1234+ glDepthFunc (GL_ALWAYS);
1235+ glStencilFunc (GL_ALWAYS, 0x55 , 0xFF );
1236+ glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
1237+ glUniform4f (colorUniformLocation, 0 .0f , 0 .0f , 1 .0f , 1 .0f );
1238+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
1239+
1240+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::blue);
1241+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , 0 , GLColor::blue);
1242+ EXPECT_PIXEL_COLOR_EQ (0 , kSize - 1 , GLColor::blue);
1243+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , kSize - 1 , GLColor::blue);
1244+
1245+ // For completeness, verify that the texture used as copy target is yellow.
1246+ ASSERT_GL_NO_ERROR ();
1247+ verifyResults (texture, GLColor::yellow, kSize , 0 , 0 , kSize , kSize );
1248+
1249+ ASSERT_GL_NO_ERROR ();
1250+ }
1251+
1252+ void MultisampledRenderToTextureTest::drawCopyDrawThenMaskedClearCommon (bool useRenderbuffer)
1253+ {
1254+ ANGLE_SKIP_TEST_IF (!EnsureGLExtensionEnabled (" GL_EXT_multisampled_render_to_texture" ));
1255+ constexpr GLsizei kSize = 64 ;
1256+
1257+ setupCopyTexProgram ();
1258+
1259+ GLFramebuffer fboMS;
1260+ glBindFramebuffer (GL_FRAMEBUFFER, fboMS);
1261+
1262+ // Create multisampled framebuffer to draw into
1263+ GLTexture textureMS;
1264+ GLRenderbuffer renderbufferMS;
1265+ createAndAttachColorAttachment (useRenderbuffer, kSize , GL_COLOR_ATTACHMENT0, nullptr ,
1266+ &textureMS, &renderbufferMS);
1267+ EXPECT_GL_FRAMEBUFFER_COMPLETE (GL_FRAMEBUFFER);
1268+
1269+ // Draw red into the multisampled color buffer.
1270+ ANGLE_GL_PROGRAM (drawColor, essl1_shaders::vs::Simple (), essl1_shaders::fs::UniformColor ());
1271+ glUseProgram (drawColor);
1272+ GLint colorUniformLocation =
1273+ glGetUniformLocation (drawColor, angle::essl1_shaders::ColorUniform ());
1274+ ASSERT_NE (colorUniformLocation, -1 );
1275+
1276+ // Draw into framebuffer.
1277+ glUniform4f (colorUniformLocation, 1 .0f , 0 .0f , 0 .0f , 1 .0f );
1278+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
1279+ ASSERT_GL_NO_ERROR ();
1280+
1281+ // Create a texture and copy into it.
1282+ GLTexture texture;
1283+ glBindTexture (GL_TEXTURE_2D, texture);
1284+ glCopyTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, 0 , 0 , kSize , kSize , 0 );
1285+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1286+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1287+
1288+ // Draw again into the framebuffer, this time blending. Afterwards, issue a masked clear. This
1289+ // ensures that previous resolved data is unresolved, and mid-render-pass clears work correctly.
1290+
1291+ // Draw green into the multisampled color buffer.
1292+ glUniform4f (colorUniformLocation, 0 .0f , 1 .0f , 0 .0f , 1 .0f );
1293+ drawQuad (drawColor, essl1_shaders::PositionAttrib (), 0 .5f );
1294+ ASSERT_GL_NO_ERROR ();
1295+
1296+ // Issue a masked clear.
1297+ glClearColor (0 .1f , 0 .9f , 1 .0f , 0 .8f );
1298+ glColorMask (GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
1299+ glClear (GL_COLOR_BUFFER_BIT);
1300+
1301+ // Verify that the texture is now cyan
1302+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::cyan);
1303+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , 0 , GLColor::cyan);
1304+ EXPECT_PIXEL_COLOR_EQ (0 , kSize - 1 , GLColor::cyan);
1305+ EXPECT_PIXEL_COLOR_EQ (kSize - 1 , kSize - 1 , GLColor::cyan);
1306+
1307+ // For completeness, verify that the texture used as copy target is red.
1308+ ASSERT_GL_NO_ERROR ();
1309+ verifyResults (texture, GLColor::red, kSize , 0 , 0 , kSize , kSize );
1310+
1311+ ASSERT_GL_NO_ERROR ();
1312+ }
1313+
1314+ // Draw, copy, draw then issue a masked clear. The copy will make sure an implicit resolve
1315+ // happens. The second draw should retain the data written by the first draw command ("unresolve"
1316+ // operation). The final clear uses a draw call to perform the clear in the Vulkan backend, and it
1317+ // should use the correct subpass index.
1318+ TEST_P (MultisampledRenderToTextureTest, DrawCopyDrawThenMaskedClear)
1319+ {
1320+ drawCopyDrawThenMaskedClearCommon (false );
1321+ }
1322+
1323+ // Same as DrawCopyDrawThenMaskedClearCommon but with renderbuffers
1324+ TEST_P (MultisampledRenderToTextureTest, RenderbufferDrawCopyDrawThenMaskedClear)
1325+ {
1326+ drawCopyDrawThenMaskedClearCommon (true );
1327+ }
1328+
11291329void MultisampledRenderToTextureTest::clearThenBlendCommon (bool useRenderbuffer)
11301330{
11311331 ANGLE_SKIP_TEST_IF (!EnsureGLExtensionEnabled (" GL_EXT_multisampled_render_to_texture" ));
0 commit comments