Closed
Bug 1380922
Opened 7 years ago
Closed 7 years ago
Make D2D singleton accessors thread-safe
Categories
(Core :: Graphics: Layers, enhancement)
Tracking
()
RESOLVED
FIXED
mozilla56
Tracking | Status | |
---|---|---|
firefox56 | --- | fixed |
People
(Reporter: dvander, Assigned: dvander)
References
Details
Attachments
(3 files, 1 obsolete file)
19.43 KB,
patch
|
mchang
:
review+
|
Details | Diff | Splinter Review |
1.74 KB,
patch
|
mchang
:
review+
|
Details | Diff | Splinter Review |
10.59 KB,
patch
|
mchang
:
review+
|
Details | Diff | Splinter Review |
According to MSDN, Direct2D is threadsafe [1], and will internally serialize draw commands on the same device. However we should make sure that the actual pointers are stored and accessed in a thread-safe way. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/jj569217(v=vs.85).aspx
Assignee | ||
Comment 1•7 years ago
|
||
This patch uses StaticRefPtr to store singletons, and RefPtr to return them.
Attachment #8886475 -
Flags: review?(mchang)
Assignee | ||
Comment 2•7 years ago
|
||
We can use mutexes to ensure that if the main thread mutates a singleton, the paint thread will have already correctly AddRef'd the old object, thus avoiding any mismatching AddRef/Release issues. It works because the return RefPtrs are constructed within the lock. (Actually hitting an issue like this should be extremely rare, but better safe than sorry.) This also forbids the paint thread from constructing singletons lazily via accessors. The main thread is responsible for doing so, and we don't want a race where the paint thread accidentally starts initializing moz2d stuff after a device reset. Instead, if the paint thread races like this, it'll get back a nullptr.
Attachment #8886477 -
Flags: review?(mchang)
Assignee | ||
Comment 3•7 years ago
|
||
Mason, should we also consider flushing the paint thread before handling a device reset?
Comment 4•7 years ago
|
||
(In reply to David Anderson [:dvander] from comment #3) > Mason, should we also consider flushing the paint thread before handling a > device reset? What happens in a device reset now?
Updated•7 years ago
|
Attachment #8886475 -
Flags: review?(mchang) → review+
Assignee | ||
Comment 5•7 years ago
|
||
(In reply to Mason Chang [:mchang] from comment #4) > (In reply to David Anderson [:dvander] from comment #3) > > Mason, should we also consider flushing the paint thread before handling a > > device reset? > > What happens in a device reset now? Right now, in theory, the painting thread could be using D2D during a device reset. Part #2 makes pointers start returning null if the paint thread tries to acquire a new singleton in the middle, and in theory the paint thread could start mixing devices together. As I say this, it sounds real bad so I think I'll do a third patch to flush the paint thread.
Comment 6•7 years ago
|
||
(In reply to David Anderson [:dvander] from comment #5) > (In reply to Mason Chang [:mchang] from comment #4) > > (In reply to David Anderson [:dvander] from comment #3) > > > Mason, should we also consider flushing the paint thread before handling a > > > device reset? > > > > What happens in a device reset now? > > Right now, in theory, the painting thread could be using D2D during a device > reset. Part #2 makes pointers start returning null if the paint thread tries > to acquire a new singleton in the middle, and in theory the paint thread > could start mixing devices together. > > As I say this, it sounds real bad so I think I'll do a third patch to flush > the paint thread. Sorry, what happens now w/o OMTP?
Assignee | ||
Comment 7•7 years ago
|
||
Since it's all single-threaded, we revoke the D2D singletons and recreate them in one go. There's no races.
Comment 8•7 years ago
|
||
Comment on attachment 8886477 [details] [diff] [review] part 2, use mutexes Review of attachment 8886477 [details] [diff] [review]: ----------------------------------------------------------------- Hopefully the locks don't show up on Talos :(. ::: gfx/2d/2D.h @@ +1692,5 @@ > static StaticRefPtr<ID2D1Device> mD2D1Device; > static StaticRefPtr<ID3D11Device> mD3D11Device; > static StaticRefPtr<IDWriteFactory> mDWriteFactory; > +protected: > + static StaticMutex mDeviceLock; nit: Add comment that says this protects the 3 things above ::: gfx/2d/Factory.cpp @@ +203,5 @@ > static uint32_t mDeviceSeq = 0; > StaticRefPtr<ID3D11Device> Factory::mD3D11Device; > StaticRefPtr<ID2D1Device> Factory::mD2D1Device; > StaticRefPtr<IDWriteFactory> Factory::mDWriteFactory; > +StaticMutex Factory::mDeviceLock; nit: Add comment stating mDeviceLock locks three things above. @@ +776,5 @@ > > + RefPtr<ID2D1Factory1> factory; > + { > + StaticMutexAutoUnlock unlock(mDeviceLock); > + factory = D2DFactory(); This is scary :(. Can we just move this up to a scoped thing at the top of the method to fetch the factory before grabing the mDeviceLock? I don't dependent locks in called functions.
Attachment #8886477 -
Flags: review?(mchang) → review+
Assignee | ||
Comment 9•7 years ago
|
||
Attachment #8886708 -
Flags: review?(mchang)
Comment 10•7 years ago
|
||
Comment on attachment 8886708 [details] [diff] [review] part 3, flush async paints Review of attachment 8886708 [details] [diff] [review]: ----------------------------------------------------------------- ::: gfx/thebes/DeviceManagerDx.cpp @@ +707,5 @@ > { > + // Flush the paint thread before revoking all these singletons. This > + // should ensure that the paint thread doesn't start mixing and matching > + // old and new objects together. > + if (XRE_IsContentProcess() && PaintThread::Get()) { nit: Don't we only need PaintThread::Get() here?
Attachment #8886708 -
Flags: review?(mchang) → review+
Assignee | ||
Comment 11•7 years ago
|
||
This version removes GetD2D1DeviceSeq, since a common pattern was to grab the lock, get the device, grab the lock again, get the sequence number. The new patch acquires both the device and sequence number with one lock.
Attachment #8886477 -
Attachment is obsolete: true
Attachment #8886720 -
Flags: review?(mchang)
Updated•7 years ago
|
Attachment #8886720 -
Flags: review?(mchang) → review+
Assignee | ||
Comment 12•7 years ago
|
||
This conflicted badly with bug 1376026, which introduced some of the fixes from this patch at the same time. As a result I merged mDeviceLock with mDWriteFactoryLock into a single StaticMutex.
Comment 13•7 years ago
|
||
Pushed by danderson@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/bc529efe4e79 Store and return D2D singletons in RefPtrs. (bug 1380922 part 1, r=mchang) https://hg.mozilla.org/integration/mozilla-inbound/rev/50011cd29784 Protect D2D singletons with a mutex. (bug 1380922 part 2, r=mchang) https://hg.mozilla.org/integration/mozilla-inbound/rev/9cd50771d27a Flush async paints before revoking device singletons. (bug 1380922 part 3, r=mchang)
Comment 14•7 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/bc529efe4e79 https://hg.mozilla.org/mozilla-central/rev/50011cd29784 https://hg.mozilla.org/mozilla-central/rev/9cd50771d27a
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
status-firefox56:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
You need to log in
before you can comment on or make changes to this bug.
Description
•