已开启
[ArkWeb][安全][自动提交] 修复 Chromium issue 513923164: Vulkan: Make sure mLargestIndexEverAllocated never decreases #460
ringking0创建于 18 天前
[ArkWeb][安全][自动提交] 修复 Chromium issue 513923164: Vulkan: Make sure mLargestIndexEverAllocated never decreases #460
已开启
共 3 个文件变更+95-4
| @@ -273,7 +273,7 @@ void AppendToPNextChain(VulkanStruct1 *chainStart, VulkanStruct2 *ptr) | |||
| 273 | class QueueSerialIndexAllocator final | 273 | class QueueSerialIndexAllocator final |
| 274 | { | 274 | { |
| 275 | public: | 275 | public: |
| 276 | - QueueSerialIndexAllocator() : mLargestIndexEverAllocated(kInvalidQueueSerialIndex) | 276 | + QueueSerialIndexAllocator() : mLargestIndexEverAllocated(0) |
| 277 | { | 277 | { |
| 278 | // Start with every index is free | 278 | // Start with every index is free |
| 279 | mFreeIndexBitSetArray.set(); | 279 | mFreeIndexBitSetArray.set(); |
| @@ -291,7 +291,8 @@ class QueueSerialIndexAllocator final | |||
| 291 | SerialIndex index = static_cast<SerialIndex>(mFreeIndexBitSetArray.first()); | 291 | SerialIndex index = static_cast<SerialIndex>(mFreeIndexBitSetArray.first()); |
| 292 | ASSERT(index < kMaxQueueSerialIndexCount); | 292 | ASSERT(index < kMaxQueueSerialIndexCount); |
| 293 | mFreeIndexBitSetArray.reset(index); | 293 | mFreeIndexBitSetArray.reset(index); |
| 294 | - mLargestIndexEverAllocated = (~mFreeIndexBitSetArray).last(); | 294 | + // Increase mLargestIndexEverAllocated to include the newly allocated index. |
| 295 | + mLargestIndexEverAllocated = std::max<size_t>(mLargestIndexEverAllocated, index); | ||
| 295 | return index; | 296 | return index; |
| 296 | } | 297 | } |
| 297 | 298 | ||
| @@ -228,7 +228,6 @@ | |||
| 228 | 42266906 : Texture2DTestES3Foveation.FoveatedFBDraw/* = SKIP_FOR_CAPTURE | 228 | 42266906 : Texture2DTestES3Foveation.FoveatedFBDraw/* = SKIP_FOR_CAPTURE |
| 229 | 42266906 : Texture2DTestES3Foveation.FoveatedTextureDraw/* = SKIP_FOR_CAPTURE | 229 | 42266906 : Texture2DTestES3Foveation.FoveatedTextureDraw/* = SKIP_FOR_CAPTURE |
| 230 | 230 | ||
| 231 | -42266965 : EGLSyncTest.GlobalFenceSync/* = FAIL | ||
| 232 | 42264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues/* = SKIP_FOR_CAPTURE | 231 | 42264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues/* = SKIP_FOR_CAPTURE |
| 233 | 42264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchBoundTextures/* = SKIP_FOR_CAPTURE | 232 | 42264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchBoundTextures/* = SKIP_FOR_CAPTURE |
| 234 | 233 | ||
| @@ -243,7 +242,7 @@ | |||
| 243 | 42264614 LINUX : VulkanExternalImageTest.UninitializedOnGLImport* = SKIP_FOR_CAPTURE | 242 | 42264614 LINUX : VulkanExternalImageTest.UninitializedOnGLImport* = SKIP_FOR_CAPTURE |
| 244 | 243 | ||
| 245 | # error: duplicate case value '1' | 244 | # error: duplicate case value '1' |
| 246 | -42264614 : EGLSyncTest.GlobalFenceSync/* = COMPILE_FAIL | 245 | +42264614 : EGLSyncTest.GlobalFenceSync*/* = COMPILE_FAIL |
| 247 | 433331119 : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = COMPILE_FAIL | 246 | 433331119 : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = COMPILE_FAIL |
| 248 | 433331119 : ValidationStateChangeTestES31.RebindVertexBufferShouldPickupBufferChange/* = COMPILE_FAIL | 247 | 433331119 : ValidationStateChangeTestES31.RebindVertexBufferShouldPickupBufferChange/* = COMPILE_FAIL |
| 249 | 248 | ||
| @@ -743,6 +743,97 @@ void main(void) | |||
| 743 | EXPECT_EGL_TRUE(eglDestroyContext(display, context2)); | 743 | EXPECT_EGL_TRUE(eglDestroyContext(display, context2)); |
| 744 | } | 744 | } |
| 745 | 745 | ||
| 746 | +// Test functionality of EGL_ANGLE_global_fence_sync in the presence of multiple threads. | ||
| 747 | +TEST_P(EGLSyncTest, GlobalFenceSyncMultithreaded) | ||
| 748 | +{ | ||
| 749 | + EGLDisplay display = getEGLWindow()->getDisplay(); | ||
| 750 | + | ||
| 751 | + ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension()); | ||
| 752 | + ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_global_fence_sync")); | ||
| 753 | + | ||
| 754 | + // Create a second context | ||
| 755 | + EGLContext context1 = eglGetCurrentContext(); | ||
| 756 | + EGLSurface drawSurface1 = eglGetCurrentSurface(EGL_DRAW); | ||
| 757 | + EGLSurface readSurface1 = eglGetCurrentSurface(EGL_READ); | ||
| 758 | + EGLConfig config = getEGLWindow()->getConfig(); | ||
| 759 | + | ||
| 760 | + const EGLint contextAttribs[] = { | ||
| 761 | + EGL_CONTEXT_CLIENT_VERSION, getEGLWindow()->getClientMajorVersion(), | ||
| 762 | + EGL_CONTEXT_MINOR_VERSION_KHR, getEGLWindow()->getClientMinorVersion(), EGL_NONE}; | ||
| 763 | + | ||
| 764 | + EGLContext context2 = eglCreateContext(display, config, context1, contextAttribs); | ||
| 765 | + ASSERT_NE(EGL_NO_CONTEXT, context2); | ||
| 766 | + | ||
| 767 | + const EGLint pbufferAttribs[] = {EGL_WIDTH, getWindowWidth(), EGL_HEIGHT, getWindowHeight(), | ||
| 768 | + EGL_NONE}; | ||
| 769 | + EGLSurface drawSurface2 = eglCreatePbufferSurface(display, config, pbufferAttribs); | ||
| 770 | + ASSERT_NE(EGL_NO_SURFACE, drawSurface2); | ||
| 771 | + | ||
| 772 | + EGLSyncKHR sync2 = EGL_NO_SYNC_KHR; | ||
| 773 | + | ||
| 774 | + // Do an expensive draw in context 2, in a thread | ||
| 775 | + std::thread slowSubmit([&]() { | ||
| 776 | + eglMakeCurrent(display, drawSurface2, drawSurface2, context2); | ||
| 777 | + | ||
| 778 | + constexpr char kCostlyVS[] = R"(attribute highp vec4 position; | ||
| 779 | + varying highp vec4 testPos; | ||
| 780 | + void main(void) | ||
| 781 | + { | ||
| 782 | + testPos = position; | ||
| 783 | + gl_Position = position; | ||
| 784 | + })"; | ||
| 785 | + | ||
| 786 | + constexpr char kCostlyFS[] = R"(precision highp float; | ||
| 787 | + varying highp vec4 testPos; | ||
| 788 | + void main(void) | ||
| 789 | + { | ||
| 790 | + vec4 test = testPos; | ||
| 791 | + for (int i = 0; i < 500; i++) | ||
| 792 | + { | ||
| 793 | + test = sqrt(test); | ||
| 794 | + } | ||
| 795 | + gl_FragColor = test; | ||
| 796 | + })"; | ||
| 797 | + | ||
| 798 | + ANGLE_GL_PROGRAM(expensiveProgram, kCostlyVS, kCostlyFS); | ||
| 799 | + drawQuad(expensiveProgram, "position", 0.0f); | ||
| 800 | + | ||
| 801 | + // Signal a fence sync for testing | ||
| 802 | + sync2 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr); | ||
| 803 | + | ||
| 804 | + // Release the context. In the Vulkan backend, this frees the queue index assigned to the | ||
| 805 | + // context. | ||
| 806 | + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | ||
| 807 | + }); | ||
| 808 | + slowSubmit.join(); | ||
| 809 | + | ||
| 810 | + // Re-make-current the context. In the Vulkan backend, this realloces the queue index assigned | ||
| 811 | + // to the context. | ||
| 812 | + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | ||
| 813 | + eglMakeCurrent(display, drawSurface1, readSurface1, context1); | ||
| 814 | + | ||
| 815 | + // Create a global fence sync | ||
| 816 | + EGLSyncKHR sync1 = eglCreateSyncKHR(display, EGL_SYNC_GLOBAL_FENCE_ANGLE, nullptr); | ||
| 817 | + | ||
| 818 | + // Wait for the global fence sync to finish. | ||
| 819 | + constexpr GLuint64 kTimeout = 2'000'000'000; // 2 seconds | ||
| 820 | + ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR, eglClientWaitSyncKHR(display, sync1, 0, kTimeout)); | ||
| 821 | + | ||
| 822 | + // If the global fence sync is signaled, then the signal from context2 must also be signaled. | ||
| 823 | + // Note that if sync1 was an EGL_SYNC_FENCE_KHR, this would not necessarily be true. | ||
| 824 | + EGLint value = 0; | ||
| 825 | + EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync2, EGL_SYNC_STATUS_KHR, &value)); | ||
| 826 | + EXPECT_EQ(value, EGL_SIGNALED_KHR); | ||
| 827 | + | ||
| 828 | + EXPECT_EQ(EGL_CONDITION_SATISFIED_KHR, eglClientWaitSyncKHR(display, sync2, 0, 0)); | ||
| 829 | + | ||
| 830 | + EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync1)); | ||
| 831 | + EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync2)); | ||
| 832 | + | ||
| 833 | + EXPECT_EGL_TRUE(eglDestroySurface(display, drawSurface2)); | ||
| 834 | + EXPECT_EGL_TRUE(eglDestroyContext(display, context2)); | ||
| 835 | +} | ||
| 836 | + | ||
| 746 | // Test that leaked fences are cleaned up in a safe way. Regression test for sync objects using tail | 837 | // Test that leaked fences are cleaned up in a safe way. Regression test for sync objects using tail |
| 747 | // calls for destruction. | 838 | // calls for destruction. |
| 748 | TEST_P(EGLSyncTest, DISABLED_LeakSyncToDisplayDestruction) | 839 | TEST_P(EGLSyncTest, DISABLED_LeakSyncToDisplayDestruction) |