已开启
[ArkWeb][安全][自动提交] 修复 Chromium issue 513048462: Fix robust resource init bypass for packed depth/stencil #462
ringking0创建于 2 天前
[ArkWeb][安全][自动提交] 修复 Chromium issue 513048462: Fix robust resource init bypass for packed depth/stencil #462
已开启
共 2 个文件变更+137-4
| @@ -1677,8 +1677,26 @@ bool Framebuffer::partialClearNeedsInit(const Context *context, | |||
| 1677 | return true; | 1677 | return true; |
| 1678 | } | 1678 | } |
| 1679 | 1679 | ||
| 1680 | + // Clearing only one aspect of a packed depth-stencil attachment is a partial | ||
| 1681 | + // clear of the underlying resource. While the framebuffer tracks depth and | ||
| 1682 | + // stencil initialization needs separately in mState.mResourceNeedsInit, the | ||
| 1683 | + // underlying resource (texture level or renderbuffer) has a single shared | ||
| 1684 | + // InitState. Marking one aspect as Initialized updates the shared resource state, | ||
| 1685 | + // which would incorrectly suppress robust-init of the other aspect. | ||
| 1686 | + if (depth && !stencil && mState.mDepthAttachment.isAttached() && | ||
| 1687 | + mState.mDepthAttachment.getStencilSize() > 0 && | ||
| 1688 | + mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT]) | ||
| 1689 | + { | ||
| 1690 | + return true; | ||
| 1691 | + } | ||
| 1692 | + if (stencil && !depth && mState.mStencilAttachment.isAttached() && | ||
| 1693 | + mState.mStencilAttachment.getDepthSize() > 0 && | ||
| 1694 | + mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT]) | ||
| 1695 | + { | ||
| 1696 | + return true; | ||
| 1697 | + } | ||
| 1698 | + | ||
| 1680 | // Scissors can affect clearing. | 1699 | // Scissors can affect clearing. |
| 1681 | - // TODO(jmadill): Check for complete scissor overlap. | ||
| 1682 | if (glState.isScissorTestEnabled()) | 1700 | if (glState.isScissorTestEnabled()) |
| 1683 | { | 1701 | { |
| 1684 | return true; | 1702 | return true; |
| @@ -3241,12 +3241,127 @@ TEST_P(RobustResourceInitTest, AttachToBoundReadFramebufferBypass) | |||
| 3241 | EXPECT_GL_NO_ERROR(); | 3241 | EXPECT_GL_NO_ERROR(); |
| 3242 | } | 3242 | } |
| 3243 | 3243 | ||
| 3244 | +// Tests that partial clear of a packed depth-stencil attachment doesn't | ||
| 3245 | +// incorrectly bypass robust initialization for the other aspect. | ||
| 3246 | +TEST_P(RobustResourceInitTestES3, DepthClearWithStencilInit) | ||
| 3247 | +{ | ||
| 3248 | + ANGLE_SKIP_TEST_IF(!hasGLExtension()); | ||
| 3249 | + | ||
| 3250 | + constexpr int kSize = 16; | ||
| 3251 | + | ||
| 3252 | + // Create a new FBO with a packed depth-stencil texture. | ||
| 3253 | + GLTexture dsTex; | ||
| 3254 | + glBindTexture(GL_TEXTURE_2D, dsTex); | ||
| 3255 | + glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize); | ||
| 3256 | + | ||
| 3257 | + GLTexture colorTex; | ||
| 3258 | + glBindTexture(GL_TEXTURE_2D, colorTex); | ||
| 3259 | + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); | ||
| 3260 | + | ||
| 3261 | + GLFramebuffer fbo; | ||
| 3262 | + glBindFramebuffer(GL_FRAMEBUFFER, fbo); | ||
| 3263 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); | ||
| 3264 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dsTex, 0); | ||
| 3265 | + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); | ||
| 3266 | + | ||
| 3267 | + // Clear only depth. This should leave the stencil aspect in MayNeedInit state, | ||
| 3268 | + // which shouldn't be overridden to Initialized. | ||
| 3269 | + glClear(GL_DEPTH_BUFFER_BIT); | ||
| 3270 | + | ||
| 3271 | + // Then bind the stencil attachment here so that we can verify it was initialized: | ||
| 3272 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dsTex, 0); | ||
| 3273 | + | ||
| 3274 | + // Verify stencil is initialized to 0. We can do this by using the stencil side channel. | ||
| 3275 | + // robust-init mandates 0. | ||
| 3276 | + glEnable(GL_STENCIL_TEST); | ||
| 3277 | + glStencilFunc(GL_EQUAL, 0x00, 0xFF); | ||
| 3278 | + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | ||
| 3279 | + | ||
| 3280 | + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); | ||
| 3281 | + drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f, 1.0f, true); | ||
| 3282 | + | ||
| 3283 | + // Read the color buffer to verify that stencil test passed for all pixels. | ||
| 3284 | + EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red); | ||
| 3285 | + EXPECT_GL_NO_ERROR(); | ||
| 3286 | +} | ||
| 3287 | + | ||
| 3288 | +// Tests that partial clear of a packed depth-stencil attachment (stencil-only) doesn't | ||
| 3289 | +// incorrectly bypass robust initialization for the depth aspect. | ||
| 3290 | +TEST_P(RobustResourceInitTestES3, StencilClearWithDepthInit) | ||
| 3291 | +{ | ||
| 3292 | + ANGLE_SKIP_TEST_IF(!hasGLExtension()); | ||
| 3293 | + | ||
| 3294 | + constexpr int kSize = 16; | ||
| 3295 | + | ||
| 3296 | + // Create a new FBO with a packed depth-stencil texture. | ||
| 3297 | + GLTexture dsTex; | ||
| 3298 | + glBindTexture(GL_TEXTURE_2D, dsTex); | ||
| 3299 | + glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize); | ||
| 3300 | + | ||
| 3301 | + GLTexture colorTex; | ||
| 3302 | + glBindTexture(GL_TEXTURE_2D, colorTex); | ||
| 3303 | + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); | ||
| 3304 | + | ||
| 3305 | + GLFramebuffer fbo; | ||
| 3306 | + glBindFramebuffer(GL_FRAMEBUFFER, fbo); | ||
| 3307 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); | ||
| 3308 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dsTex, 0); | ||
| 3309 | + EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); | ||
| 3310 | + | ||
| 3311 | + // Clear only stencil. This should leave the depth aspect in MayNeedInit state, | ||
| 3312 | + // which shouldn't be overridden to Initialized. | ||
| 3313 | + glClear(GL_STENCIL_BUFFER_BIT); | ||
| 3314 | + | ||
| 3315 | + // Unbind the depth-stencil texture from the FBO so we can sample it as a texture. | ||
| 3316 | + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 3317 | + | ||
| 3318 | + // Bind the texture to texture unit 0 and set filters. | ||
| 3319 | + glActiveTexture(GL_TEXTURE0); | ||
| 3320 | + glBindTexture(GL_TEXTURE_2D, dsTex); | ||
| 3321 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
| 3322 | + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
| 3323 | + | ||
| 3324 | + // Verify depth == 1.0 via shader sampling | ||
| 3325 | + constexpr char kVS[] = R"(#version 300 es | ||
| 3326 | +in vec4 aPosition; | ||
| 3327 | +void main() | ||
| 3328 | +{ | ||
| 3329 | + gl_Position = aPosition; | ||
| 3330 | +})"; | ||
| 3331 | + | ||
| 3332 | + constexpr char kFS[] = R"(#version 300 es | ||
| 3333 | +precision highp float; | ||
| 3334 | +uniform highp sampler2D uDepthTex; | ||
| 3335 | +out vec4 outColor; | ||
| 3336 | +void main() | ||
| 3337 | +{ | ||
| 3338 | + float depth = texture(uDepthTex, vec2(0.5, 0.5)).r; | ||
| 3339 | + if (abs(depth - 1.0) < 0.001) | ||
| 3340 | + { | ||
| 3341 | + outColor = vec4(0.0, 1.0, 0.0, 1.0); // green | ||
| 3342 | + } | ||
| 3343 | + else | ||
| 3344 | + { | ||
| 3345 | + outColor = vec4(1.0, 0.0, 0.0, 1.0); // red | ||
| 3346 | + } | ||
| 3347 | +})"; | ||
| 3348 | + | ||
| 3349 | + ANGLE_GL_PROGRAM(depthSampleProg, kVS, kFS); | ||
| 3350 | + glUseProgram(depthSampleProg); | ||
| 3351 | + GLint texLoc = glGetUniformLocation(depthSampleProg, "uDepthTex"); | ||
| 3352 | + ASSERT_NE(texLoc, -1); | ||
| 3353 | + glUniform1i(texLoc, 0); | ||
| 3354 | + | ||
| 3355 | + drawQuad(depthSampleProg, "aPosition", 0.0f); | ||
| 3356 | + | ||
| 3357 | + // Read the color buffer to verify that depth was successfully initialized to 1.0f. | ||
| 3358 | + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); | ||
| 3359 | + EXPECT_GL_NO_ERROR(); | ||
| 3360 | +} | ||
| 3361 | + | ||
| 3244 | ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( | 3362 | ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( |
| 3245 | RobustResourceInitTest, | 3363 | RobustResourceInitTest, |
| 3246 | ES3_METAL().enable(Feature::EmulateDontCareLoadWithRandomClear), | 3364 | ES3_METAL().enable(Feature::EmulateDontCareLoadWithRandomClear), |
| 3247 | - ES3_METAL().enable(Feature::AllocateNonZeroTextures), | ||
| 3248 | - ES2_METAL().enable(Feature::AllocateNonZeroTextures), | ||
| 3249 | - ES2_VULKAN().enable(Feature::AllocateNonZeroMemory)); | ||
| 3250 | 3365 | ||
| 3251 | GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustResourceInitTestES3); | 3366 | GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustResourceInitTestES3); |
| 3252 | ANGLE_INSTANTIATE_TEST_ES3_AND(RobustResourceInitTestES3, | 3367 | ANGLE_INSTANTIATE_TEST_ES3_AND(RobustResourceInitTestES3, |