已开启
[ArkWeb][安全][自动提交] 修复 Chromium issue 513923164: Vulkan: Make sure mLargestIndexEverAllocated never decreases #460
[ArkWeb][安全][自动提交] 修复 Chromium issue 513923164: Vulkan: Make sure mLargestIndexEverAllocated never decreases #460
已开启
ringking0创建于 18 天前
3 个文件变更+95-4
@@ -273,7 +273,7 @@ void AppendToPNextChain(VulkanStruct1 *chainStart, VulkanStruct2 *ptr)
273class QueueSerialIndexAllocator final273class QueueSerialIndexAllocator final
274{274{
275 public:275 public:
276- QueueSerialIndexAllocator() : mLargestIndexEverAllocated(kInvalidQueueSerialIndex)276+ QueueSerialIndexAllocator() : mLargestIndexEverAllocated(0)
277 {277 {
278 // Start with every index is free278 // 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 @@
22842266906 : Texture2DTestES3Foveation.FoveatedFBDraw/* = SKIP_FOR_CAPTURE22842266906 : Texture2DTestES3Foveation.FoveatedFBDraw/* = SKIP_FOR_CAPTURE
22942266906 : Texture2DTestES3Foveation.FoveatedTextureDraw/* = SKIP_FOR_CAPTURE22942266906 : Texture2DTestES3Foveation.FoveatedTextureDraw/* = SKIP_FOR_CAPTURE
230 230 
231-42266965 : EGLSyncTest.GlobalFenceSync/* = FAIL
23242264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues/* = SKIP_FOR_CAPTURE23142264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues/* = SKIP_FOR_CAPTURE
23342264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchBoundTextures/* = SKIP_FOR_CAPTURE23242264309 : Texture2DTestES3.TexStorage2DMultipleYuvSamplersSwitchBoundTextures/* = SKIP_FOR_CAPTURE
234 233 
@@ -243,7 +242,7 @@
24342264614 LINUX : VulkanExternalImageTest.UninitializedOnGLImport* = SKIP_FOR_CAPTURE24242264614 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_FAIL245+42264614 : EGLSyncTest.GlobalFenceSync*/* = COMPILE_FAIL
247433331119 : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = COMPILE_FAIL246433331119 : ValidationStateChangeTest.RebindBufferShouldPickupBufferChange/* = COMPILE_FAIL
248433331119 : ValidationStateChangeTestES31.RebindVertexBufferShouldPickupBufferChange/* = COMPILE_FAIL247433331119 : 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 tail837// 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.
748TEST_P(EGLSyncTest, DISABLED_LeakSyncToDisplayDestruction)839TEST_P(EGLSyncTest, DISABLED_LeakSyncToDisplayDestruction)