⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 271212 in webkit


Ignore:
Timestamp:
Jan 6, 2021, 12:35:27 PM (6 years ago)
Author:
Wenson Hsieh
Message:

[Concurrent Display Lists] GPU process should not immediately sleep after reading all available display list items
https://bugs.webkit.org/show_bug.cgi?id=219586
<rdar://problem/72275412>

Reviewed by Chris Dumez.

This patch adds a mechanism for the GPU process to wait for a short duration (~30 microseconds) after it has
finished reading all available data in its shared item buffer; if the web process writes additional data to the
item buffer (thereby bumping the unread bytes counter) during this time, we immediately resume processing the
new display list items in the GPU process, rather than wait for a new wakeup message.

This allows us to avoid the cost of going to sleep just to immediately wake up in the GPU process, in the case
where the web process is writing display list items at a very fast rate and the GPU process just happens to
catch up (i.e. advance unreadBytes() to 0).

See below for more details.

  • GPUProcess/GPUConnectionToWebProcess.cpp:

(WebKit::GPUConnectionToWebProcess::createRenderingBackend):

Refactor the rendering backend creation message from the web process to the GPU process, so that the rendering
backend creation arguments are encapsulated in a single struct, RemoteRenderingBackendCreationParameters. This
struct contains the rendering backend identifier and, on Cocoa platforms, a mach send right that can be used to
construct the corresponding display list wakeup semaphore in the GPU process.

  • GPUProcess/GPUConnectionToWebProcess.h:
  • GPUProcess/GPUConnectionToWebProcess.messages.in:
  • GPUProcess/graphics/DisplayListReaderHandle.h:

(WebKit::DisplayListReaderHandle::startWaiting):
(WebKit::DisplayListReaderHandle::stopWaiting):

Add helper methods for the GPU process to start and stop waiting for new items. See the call site in
RemoteRenderingBackend for more detail, as well as the comments in SharedDisplayListHandle below.

  • GPUProcess/graphics/RemoteRenderingBackend.cpp:

(WebKit::RemoteRenderingBackend::create):
(WebKit::RemoteRenderingBackend::RemoteRenderingBackend):

Refactor this codepath to take RemoteRenderingBackendCreationParameters instead of just an identifier.

(WebKit::RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists):

In the case where we received the wakeup message due to exceeding the display list item count hysteresis, wait
for a short duration using the semaphore after we hit an unread count of 0. This allows the web process to write
more items and signal the semaphore, so that we can resume reading in the GPU process.

(WebKit::RemoteRenderingBackend::wakeUpAndApplyDisplayList):
(WebKit::RemoteRenderingBackend::setNextItemBufferToRead):

  • GPUProcess/graphics/RemoteRenderingBackend.h:
  • Shared/GPUProcessWakeupMessageArguments.h:

(WebKit::GPUProcessWakeupMessageArguments::encode const):
(WebKit::GPUProcessWakeupMessageArguments::decode):

Plumb a GPUProcessWakeupReason enum flag over to the GPU process, via wake-up arguments. This flag is used by
the GPU process to determine whether we should expect additional items to eventually enter the stream, and
whether we should eagerly go to sleep after processing all known items. In other words, if the wakeup message is
being sent as a result of flushing the image buffer, we don't want to unnecessarily wait for more items;
however, if the wakeup message is being sent as a result of exceeding the (currently) 512-item hysteresis, then
we can probably expect more items to stream in, so it's more optimal to wait after finishing all known display
list items.

  • Shared/RemoteRenderingBackendCreationParameters.h: Copied from Source/WebKit/Shared/GPUProcessWakeupMessageArguments.h.

(WebKit::RemoteRenderingBackendCreationParameters::encode const):
(WebKit::RemoteRenderingBackendCreationParameters::decode):

See above for more details.

  • Shared/SharedDisplayListHandle.h:

(WebKit::SharedDisplayListHandle::header const):

Adds a new WaitingStatus enum type internal to SharedDisplayListHandle and its subclasses, which is used to
coordinate the act of waiting for new item data in the GPU process. A shared display list handle now contains
an atomic waitingStatus flag indicating whether the GPU process is in the process of waiting for more items,
and also whether the web process has acknowledged the fact that the GPU process is waiting (thereby putting the
GPU process in a state where it is waiting to resume processing). Along with this enum, we also add two new
8-byte values to the header section: an offset to begin reading item data after resuming, and 8 bytes for an
identifier indicating the new destination (for the purposes of display list rendering, this is a
RenderingResourceIdentifier, though this will be different for WebGL).

+--> NotWaiting <--+
| | |
| | | [3a]
| [3b] | [1] |
| | |

Resuming +----> Waiting

|
| [2] |
+------------------+

There are three main ways in which this state machine may transition, numbered [1]-[3] in the above diagram.

[1] When the GPU process finishes processing available items, it enters Waiting state, indicating that it is now

waiting for additional item data. This corresponds to the call to DisplayListReaderHandle::startWaiting.

[2] When the web process bumps the unread count of an item buffer, if it has a pending wakeup message or would

otherwise need to schedule a pending wakeup message, see if we can instead simply tell the GPU process to
resume processing, instead of sending a wakeup message. This corresponds to a call to the helper method
DisplayListWriterHandle::tryToResume.

[3] If the maximum wait duration (~30 microseconds) has passed (i.e. scenario 3a) or if the web process has

transitioned us from Waiting to Resuming state (i.e. scenario 3b), then transition back to NotWaiting. In
both scenarios, this corresponds to a call to DisplayListReaderHandle::stopWaiting. In the case where we
transitioned from Resuming state, we can immediately continue processing display list items.

In the case where we successfully resume, we're essentially "re-waking" the GPU process without the overhead of
an additional IPC message, using the same shared display list handle. Since this would've otherwise been a
separate wakeup message, we need to be careful that we continue processing display list items from the correct
offset into the shared display list handle, and using the correct destination image buffer. This is because the
writable offset of the item buffer may have been reset in the middle of waiting by the web process, or the
destination image buffer may have changed while waiting. To handle these scenarios, we introduce the
ResumeReadingInformation struct, which contains both of these pieces of information. An instance of this
struct exists in the shared memory header section; this is written by the web process immediately prior to
transitioning to Resuming state, and read by the GPU process when transitioning from Resuming to NotWaiting.

  • WebKit.xcodeproj/project.pbxproj:
  • WebProcess/GPU/graphics/DisplayListWriterHandle.h:

(WebKit::DisplayListWriterHandle::tryToResume):

Add a helper method for the web process to try and notify the GPU process that it should try and resume
display list processing. See the call site in RemoteRenderingBackendProxy for more detail, as well as the
comments in SharedDisplayListHandle above.

  • WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:

(WebKit::RemoteRenderingBackendProxy::connectToGPUProcess):
(WebKit::RemoteRenderingBackendProxy::didAppendData):

Rather than always schedule (or send) a wakeup message here in the case where the unread count is 0, see if we
can instead tell the GPU process to stop waiting and resume display list processing. To do this, we use the new
DisplayListWriterHandle::tryToResume method, giving it the new offset to begin reading items from as well as the
destination image buffer to which we should apply display list items. If we successfully tell the GPU process to
resume reading, then we can clear out (or avoid storing) wakeup message arguments and avoid sending an IPC
wakeup message.

  • WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:
Location:
trunk/Source/WebKit
Files:
13 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r271207 r271212  
     12021-01-06  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Concurrent Display Lists] GPU process should not immediately sleep after reading all available display list items
     4        https://bugs.webkit.org/show_bug.cgi?id=219586
     5        <rdar://problem/72275412>
     6
     7        Reviewed by Chris Dumez.
     8
     9        This patch adds a mechanism for the GPU process to wait for a short duration (~30 microseconds) after it has
     10        finished reading all available data in its shared item buffer; if the web process writes additional data to the
     11        item buffer (thereby bumping the unread bytes counter) during this time, we immediately resume processing the
     12        new display list items in the GPU process, rather than wait for a new wakeup message.
     13
     14        This allows us to avoid the cost of going to sleep just to immediately wake up in the GPU process, in the case
     15        where the web process is writing display list items at a very fast rate and the GPU process just happens to
     16        catch up (i.e. advance `unreadBytes()` to 0).
     17
     18        See below for more details.
     19
     20        * GPUProcess/GPUConnectionToWebProcess.cpp:
     21        (WebKit::GPUConnectionToWebProcess::createRenderingBackend):
     22
     23        Refactor the rendering backend creation message from the web process to the GPU process, so that the rendering
     24        backend creation arguments are encapsulated in a single struct, RemoteRenderingBackendCreationParameters. This
     25        struct contains the rendering backend identifier and, on Cocoa platforms, a mach send right that can be used to
     26        construct the corresponding display list wakeup semaphore in the GPU process.
     27
     28        * GPUProcess/GPUConnectionToWebProcess.h:
     29        * GPUProcess/GPUConnectionToWebProcess.messages.in:
     30        * GPUProcess/graphics/DisplayListReaderHandle.h:
     31        (WebKit::DisplayListReaderHandle::startWaiting):
     32        (WebKit::DisplayListReaderHandle::stopWaiting):
     33
     34        Add helper methods for the GPU process to start and stop waiting for new items. See the call site in
     35        RemoteRenderingBackend for more detail, as well as the comments in SharedDisplayListHandle below.
     36
     37        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
     38        (WebKit::RemoteRenderingBackend::create):
     39        (WebKit::RemoteRenderingBackend::RemoteRenderingBackend):
     40
     41        Refactor this codepath to take RemoteRenderingBackendCreationParameters instead of just an identifier.
     42
     43        (WebKit::RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists):
     44
     45        In the case where we received the wakeup message due to exceeding the display list item count hysteresis, wait
     46        for a short duration using the semaphore after we hit an unread count of 0. This allows the web process to write
     47        more items and signal the semaphore, so that we can resume reading in the GPU process.
     48
     49        (WebKit::RemoteRenderingBackend::wakeUpAndApplyDisplayList):
     50        (WebKit::RemoteRenderingBackend::setNextItemBufferToRead):
     51        * GPUProcess/graphics/RemoteRenderingBackend.h:
     52        * Shared/GPUProcessWakeupMessageArguments.h:
     53        (WebKit::GPUProcessWakeupMessageArguments::encode const):
     54        (WebKit::GPUProcessWakeupMessageArguments::decode):
     55
     56        Plumb a GPUProcessWakeupReason enum flag over to the GPU process, via wake-up arguments. This flag is used by
     57        the GPU process to determine whether we should expect additional items to eventually enter the stream, and
     58        whether we should eagerly go to sleep after processing all known items. In other words, if the wakeup message is
     59        being sent as a result of flushing the image buffer, we don't want to unnecessarily wait for more items;
     60        however, if the wakeup message is being sent as a result of exceeding the (currently) 512-item hysteresis, then
     61        we can probably expect more items to stream in, so it's more optimal to wait after finishing all known display
     62        list items.
     63
     64        * Shared/RemoteRenderingBackendCreationParameters.h: Copied from Source/WebKit/Shared/GPUProcessWakeupMessageArguments.h.
     65        (WebKit::RemoteRenderingBackendCreationParameters::encode const):
     66        (WebKit::RemoteRenderingBackendCreationParameters::decode):
     67
     68        See above for more details.
     69
     70        * Shared/SharedDisplayListHandle.h:
     71        (WebKit::SharedDisplayListHandle::header const):
     72
     73        Adds a new WaitingStatus enum type internal to SharedDisplayListHandle and its subclasses, which is used to
     74        coordinate the act of waiting for new item data in the GPU process. A shared display list handle now contains
     75        an atomic `waitingStatus` flag indicating whether the GPU process is in the process of waiting for more items,
     76        and also whether the web process has acknowledged the fact that the GPU process is waiting (thereby putting the
     77        GPU process in a state where it is waiting to resume processing). Along with this enum, we also add two new
     78        8-byte values to the header section: an offset to begin reading item data after resuming, and 8 bytes for an
     79        identifier indicating the new destination (for the purposes of display list rendering, this is a
     80        RenderingResourceIdentifier, though this will be different for WebGL).
     81
     82            +--> NotWaiting <--+
     83            |        |         |
     84            |        |         | [3a]
     85            | [3b]   | [1]     |
     86            |        |         |
     87        Resuming     +----> Waiting
     88            ^                  |
     89            |        [2]       |
     90            +------------------+
     91
     92        There are three main ways in which this state machine may transition, numbered [1]-[3] in the above diagram.
     93
     94        [1] When the GPU process finishes processing available items, it enters Waiting state, indicating that it is now
     95            waiting for additional item data. This corresponds to the call to `DisplayListReaderHandle::startWaiting`.
     96
     97        [2] When the web process bumps the unread count of an item buffer, if it has a pending wakeup message or would
     98            otherwise need to schedule a pending wakeup message, see if we can instead simply tell the GPU process to
     99            resume processing, instead of sending a wakeup message. This corresponds to a call to the helper method
     100            `DisplayListWriterHandle::tryToResume`.
     101
     102        [3] If the maximum wait duration (~30 microseconds) has passed (i.e. scenario 3a) or if the web process has
     103            transitioned us from Waiting to Resuming state (i.e. scenario 3b), then transition back to NotWaiting. In
     104            both scenarios, this corresponds to a call to `DisplayListReaderHandle::stopWaiting`. In the case where we
     105            transitioned from Resuming state, we can immediately continue processing display list items.
     106
     107        In the case where we successfully resume, we're essentially "re-waking" the GPU process without the overhead of
     108        an additional IPC message, using the same shared display list handle. Since this would've otherwise been a
     109        separate wakeup message, we need to be careful that we continue processing display list items from the correct
     110        offset into the shared display list handle, and using the correct destination image buffer. This is because the
     111        writable offset of the item buffer may have been reset in the middle of waiting by the web process, or the
     112        destination image buffer may have changed while waiting. To handle these scenarios, we introduce the
     113        `ResumeReadingInformation` struct, which contains both of these pieces of information. An instance of this
     114        struct exists in the shared memory header section; this is written by the web process immediately prior to
     115        transitioning to Resuming state, and read by the GPU process when transitioning from Resuming to NotWaiting.
     116
     117        * WebKit.xcodeproj/project.pbxproj:
     118        * WebProcess/GPU/graphics/DisplayListWriterHandle.h:
     119        (WebKit::DisplayListWriterHandle::tryToResume):
     120
     121        Add a helper method for the web process to try and notify the GPU process that it should try and resume
     122        display list processing. See the call site in RemoteRenderingBackendProxy for more detail, as well as the
     123        comments in SharedDisplayListHandle above.
     124
     125        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
     126        (WebKit::RemoteRenderingBackendProxy::connectToGPUProcess):
     127        (WebKit::RemoteRenderingBackendProxy::didAppendData):
     128
     129        Rather than always schedule (or send) a wakeup message here in the case where the unread count is 0, see if we
     130        can instead tell the GPU process to stop waiting and resume display list processing. To do this, we use the new
     131        DisplayListWriterHandle::tryToResume method, giving it the new offset to begin reading items from as well as the
     132        destination image buffer to which we should apply display list items. If we successfully tell the GPU process to
     133        resume reading, then we can clear out (or avoid storing) wakeup message arguments and avoid sending an IPC
     134        wakeup message.
     135
     136        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:
     137
    11382021-01-06  Alex Christensen  <achristensen@webkit.org>
    2139
  • trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp

    r270720 r271212  
    4949#include "RemoteMediaResourceManagerMessages.h"
    5050#include "RemoteRenderingBackend.h"
     51#include "RemoteRenderingBackendCreationParameters.h"
    5152#include "RemoteSampleBufferDisplayLayerManager.h"
    5253#include "RemoteSampleBufferDisplayLayerManagerMessages.h"
     
    289290#endif
    290291
    291 void GPUConnectionToWebProcess::createRenderingBackend(RenderingBackendIdentifier renderingBackendIdentifier)
    292 {
    293     auto addResult = m_remoteRenderingBackendMap.ensure(renderingBackendIdentifier, [&]() {
    294         return RemoteRenderingBackend::create(*this, renderingBackendIdentifier);
     292void GPUConnectionToWebProcess::createRenderingBackend(RemoteRenderingBackendCreationParameters&& parameters)
     293{
     294    auto addResult = m_remoteRenderingBackendMap.ensure(parameters.identifier, [&]() {
     295        return RemoteRenderingBackend::create(*this, WTFMove(parameters));
    295296    });
    296297    ASSERT_UNUSED(addResult, addResult.isNewEntry);
  • trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h

    r270720 r271212  
    6666class UserMediaCaptureManagerProxy;
    6767struct RemoteAudioSessionConfiguration;
     68struct RemoteRenderingBackendCreationParameters;
    6869
    6970class GPUConnectionToWebProcess
     
    125126#endif
    126127
    127     void createRenderingBackend(RenderingBackendIdentifier);
     128    void createRenderingBackend(RemoteRenderingBackendCreationParameters&&);
    128129    void releaseRenderingBackend(RenderingBackendIdentifier);
    129130
  • trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.messages.in

    r270720 r271212  
    2424
    2525messages -> GPUConnectionToWebProcess WantsDispatchMessage {
    26     void CreateRenderingBackend(WebKit::RenderingBackendIdentifier renderingBackendIdentifier)
     26    void CreateRenderingBackend(struct WebKit::RemoteRenderingBackendCreationParameters parameters)
    2727    void ReleaseRenderingBackend(WebKit::RenderingBackendIdentifier renderingBackendIdentifier)
    2828#if ENABLE(WEBGL)
  • trunk/Source/WebKit/GPUProcess/graphics/DisplayListReaderHandle.h

    r269682 r271212  
    4242    std::unique_ptr<WebCore::DisplayList::DisplayList> displayListForReading(size_t offset, size_t capacity, WebCore::DisplayList::ItemBufferReadingClient&) const;
    4343
     44    void startWaiting()
     45    {
     46        header().waitingStatus.store(SharedDisplayListHandle::WaitingStatus::Waiting);
     47    }
     48
     49    Optional<SharedDisplayListHandle::ResumeReadingInformation> stopWaiting()
     50    {
     51        auto& header = this->header();
     52        if (header.waitingStatus.exchange(SharedDisplayListHandle::WaitingStatus::NotWaiting) == SharedDisplayListHandle::WaitingStatus::Resuming)
     53            return { header.resumeReadingInfo };
     54
     55        return WTF::nullopt;
     56    }
     57
    4458private:
    4559    DisplayListReaderHandle(WebCore::DisplayList::ItemBufferIdentifier identifier, Ref<SharedMemory>&& sharedMemory)
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp

    r271036 r271212  
    3434#include "RemoteMediaPlayerManagerProxy.h"
    3535#include "RemoteMediaPlayerProxy.h"
     36#include "RemoteRenderingBackendCreationParameters.h"
    3637#include "RemoteRenderingBackendMessages.h"
    3738#include "RemoteRenderingBackendProxyMessages.h"
     
    3940#include <wtf/SystemTracing.h>
    4041
     42#if PLATFORM(COCOA)
     43#include <wtf/cocoa/MachSemaphore.h>
     44#endif
     45
    4146namespace WebKit {
    4247using namespace WebCore;
    4348
    44 std::unique_ptr<RemoteRenderingBackend> RemoteRenderingBackend::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RenderingBackendIdentifier renderingBackendIdentifier)
    45 {
    46     return std::unique_ptr<RemoteRenderingBackend>(new RemoteRenderingBackend(gpuConnectionToWebProcess, renderingBackendIdentifier));
    47 }
    48 
    49 RemoteRenderingBackend::RemoteRenderingBackend(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RenderingBackendIdentifier renderingBackendIdentifier)
     49std::unique_ptr<RemoteRenderingBackend> RemoteRenderingBackend::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RemoteRenderingBackendCreationParameters&& parameters)
     50{
     51    return std::unique_ptr<RemoteRenderingBackend>(new RemoteRenderingBackend(gpuConnectionToWebProcess, WTFMove(parameters)));
     52}
     53
     54RemoteRenderingBackend::RemoteRenderingBackend(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RemoteRenderingBackendCreationParameters&& parameters)
    5055    : m_gpuConnectionToWebProcess(makeWeakPtr(gpuConnectionToWebProcess))
    51     , m_renderingBackendIdentifier(renderingBackendIdentifier)
     56    , m_renderingBackendIdentifier(parameters.identifier)
     57#if PLATFORM(COCOA)
     58    , m_resumeDisplayListSemaphore(makeUnique<MachSemaphore>(WTFMove(parameters.sendRightForResumeDisplayListSemaphore)))
     59#endif
    5260{
    5361    if (auto* gpuConnectionToWebProcess = m_gpuConnectionToWebProcess.get())
    54         gpuConnectionToWebProcess->messageReceiverMap().addMessageReceiver(Messages::RemoteRenderingBackend::messageReceiverName(), renderingBackendIdentifier.toUInt64(), *this);
     62        gpuConnectionToWebProcess->messageReceiverMap().addMessageReceiver(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this);
    5563}
    5664
     
    154162}
    155163
    156 RefPtr<ImageBuffer> RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists(ImageBuffer& initialDestination, size_t initialOffset, DisplayListReaderHandle& handle)
     164RefPtr<ImageBuffer> RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists(ImageBuffer& initialDestination, size_t initialOffset, DisplayListReaderHandle& handle, GPUProcessWakeupReason reason)
    157165{
    158166    auto destination = makeRefPtr(initialDestination);
     
    196204            if (!destination) {
    197205                ASSERT(!m_pendingWakeupInfo);
    198                 m_pendingWakeupInfo = {{{ handle.identifier(), offset, *result.nextDestinationImageBuffer }, WTF::nullopt }};
     206                m_pendingWakeupInfo = {{{ handle.identifier(), offset, *result.nextDestinationImageBuffer, reason }, WTF::nullopt }};
    199207            }
    200208        }
     
    202210        if (result.reasonForStopping == DisplayList::StopReplayReason::MissingCachedResource) {
    203211            m_pendingWakeupInfo = {{
    204                 { handle.identifier(), offset, destination->renderingResourceIdentifier() },
     212                { handle.identifier(), offset, destination->renderingResourceIdentifier(), reason },
    205213                result.missingCachedResourceIdentifier
    206214            }};
     
    210218            break;
    211219
    212         if (!sizeToRead)
    213             break;
     220        if (!sizeToRead) {
     221            if (reason != GPUProcessWakeupReason::ItemCountHysteresisExceeded)
     222                break;
     223
     224            handle.startWaiting();
     225#if PLATFORM(COCOA)
     226            m_resumeDisplayListSemaphore->waitFor(30_us);
     227#else
     228            sleep(30_us);
     229#endif
     230
     231            auto resumeReadingInfo = handle.stopWaiting();
     232            if (!resumeReadingInfo)
     233                break;
     234
     235            sizeToRead = handle.unreadBytes();
     236            if (UNLIKELY(!sizeToRead)) {
     237                // FIXME: Add a message check to terminate the web process.
     238                ASSERT_NOT_REACHED();
     239                break;
     240            }
     241
     242            auto newDestinationIdentifier = makeObjectIdentifier<RenderingResourceIdentifierType>(resumeReadingInfo->destination);
     243            if (UNLIKELY(!newDestinationIdentifier)) {
     244                // FIXME: Add a message check to terminate the web process.
     245                ASSERT_NOT_REACHED();
     246                break;
     247            }
     248
     249            destination = makeRefPtr(m_remoteResourceCache.cachedImageBuffer(newDestinationIdentifier));
     250
     251            if (UNLIKELY(!destination)) {
     252                // FIXME: Add a message check to terminate the web process.
     253                ASSERT_NOT_REACHED();
     254                break;
     255            }
     256
     257            offset = resumeReadingInfo->offset;
     258
     259            if (!destination) {
     260                ASSERT(!m_pendingWakeupInfo);
     261                m_pendingWakeupInfo = {{{ handle.identifier(), offset, newDestinationIdentifier, reason }, WTF::nullopt }};
     262                break;
     263            }
     264        }
    214265    }
    215266
     
    234285    }
    235286
    236     destinationImageBuffer = nextDestinationImageBufferAfterApplyingDisplayLists(*destinationImageBuffer, arguments.offset, *initialHandle);
     287    destinationImageBuffer = nextDestinationImageBufferAfterApplyingDisplayLists(*destinationImageBuffer, arguments.offset, *initialHandle, arguments.reason);
    237288    if (!destinationImageBuffer) {
    238289        RELEASE_ASSERT(m_pendingWakeupInfo);
     
    253304        // Otherwise, continue reading the next display list item buffer from the start.
    254305        auto arguments = std::exchange(m_pendingWakeupInfo, WTF::nullopt)->arguments;
    255         destinationImageBuffer = nextDestinationImageBufferAfterApplyingDisplayLists(*destinationImageBuffer, arguments.offset, *nextHandle);
     306        destinationImageBuffer = nextDestinationImageBufferAfterApplyingDisplayLists(*destinationImageBuffer, arguments.offset, *nextHandle, arguments.reason);
    256307        if (!destinationImageBuffer) {
    257308            RELEASE_ASSERT(m_pendingWakeupInfo);
     
    268319        return;
    269320    }
    270     m_pendingWakeupInfo = {{{ identifier, SharedDisplayListHandle::headerSize(), destinationIdentifier }, WTF::nullopt }};
     321    m_pendingWakeupInfo = {{{ identifier, SharedDisplayListHandle::headerSize(), destinationIdentifier, GPUProcessWakeupReason::Unspecified }, WTF::nullopt }};
    271322}
    272323
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h

    r271036 r271212  
    4242#include <wtf/WeakPtr.h>
    4343
     44#if PLATFORM(COCOA)
     45namespace WTF {
     46class MachSemaphore;
     47}
     48#endif
     49
    4450namespace WebCore {
    4551namespace DisplayList {
     
    5763class DisplayListReaderHandle;
    5864class GPUConnectionToWebProcess;
     65struct RemoteRenderingBackendCreationParameters;
    5966
    6067class RemoteRenderingBackend
     
    6370    , public WebCore::DisplayList::ItemBufferReadingClient {
    6471public:
    65     static std::unique_ptr<RemoteRenderingBackend> create(GPUConnectionToWebProcess&, RenderingBackendIdentifier);
     72    static std::unique_ptr<RemoteRenderingBackend> create(GPUConnectionToWebProcess&, RemoteRenderingBackendCreationParameters&&);
    6673    virtual ~RemoteRenderingBackend();
    6774
     
    7986
    8087private:
    81     RemoteRenderingBackend(GPUConnectionToWebProcess&, RenderingBackendIdentifier);
     88    RemoteRenderingBackend(GPUConnectionToWebProcess&, RemoteRenderingBackendCreationParameters&&);
    8289
    8390    Optional<WebCore::DisplayList::ItemHandle> WARN_UNUSED_RETURN decodeItem(const uint8_t* data, size_t length, WebCore::DisplayList::ItemType, uint8_t* handleLocation) override;
     
    96103
    97104    WebCore::DisplayList::ReplayResult submit(const WebCore::DisplayList::DisplayList&, WebCore::ImageBuffer& destination);
    98     RefPtr<WebCore::ImageBuffer> nextDestinationImageBufferAfterApplyingDisplayLists(WebCore::ImageBuffer& initialDestination, size_t initialOffset, DisplayListReaderHandle&);
     105    RefPtr<WebCore::ImageBuffer> nextDestinationImageBufferAfterApplyingDisplayLists(WebCore::ImageBuffer& initialDestination, size_t initialOffset, DisplayListReaderHandle&, GPUProcessWakeupReason);
    99106
    100107    // IPC::MessageSender.
     
    140147    HashMap<WebCore::DisplayList::ItemBufferIdentifier, RefPtr<DisplayListReaderHandle>> m_sharedDisplayListHandles;
    141148    Optional<PendingWakeupInformation> m_pendingWakeupInfo;
     149#if PLATFORM(COCOA)
     150    std::unique_ptr<WTF::MachSemaphore> m_resumeDisplayListSemaphore;
     151#endif
    142152};
    143153
  • trunk/Source/WebKit/Shared/GPUProcessWakeupMessageArguments.h

    r270564 r271212  
    3333namespace WebKit {
    3434
     35enum class GPUProcessWakeupReason : uint8_t {
     36    Unspecified,
     37    ItemCountHysteresisExceeded
     38};
     39
    3540struct GPUProcessWakeupMessageArguments {
    3641    WebCore::DisplayList::ItemBufferIdentifier itemBufferIdentifier;
    3742    uint64_t offset { 0 };
    3843    WebCore::RenderingResourceIdentifier destinationImageBufferIdentifier;
     44    GPUProcessWakeupReason reason { GPUProcessWakeupReason::Unspecified };
    3945
    4046    template<class Encoder> void encode(Encoder&) const;
     
    4854    encoder << offset;
    4955    encoder << destinationImageBufferIdentifier;
     56    encoder << reason;
    5057}
    5158
     
    6875        return WTF::nullopt;
    6976
    70     return {{ *itemBufferIdentifier, *offset, *destinationImageBufferIdentifier }};
     77    Optional<GPUProcessWakeupReason> reason;
     78    decoder >> reason;
     79    if (!reason)
     80        return WTF::nullopt;
     81
     82    return {{ *itemBufferIdentifier, *offset, *destinationImageBufferIdentifier, *reason }};
    7183}
    7284
    7385} // namespace WebKit
    7486
     87namespace WTF {
     88
     89template<> struct EnumTraits<WebKit::GPUProcessWakeupReason> {
     90    using values = EnumValues<
     91        WebKit::GPUProcessWakeupReason,
     92        WebKit::GPUProcessWakeupReason::Unspecified,
     93        WebKit::GPUProcessWakeupReason::ItemCountHysteresisExceeded
     94    >;
     95};
     96
     97} // namespace WTF
     98
    7599#endif // ENABLE(GPU_PROCESS)
  • trunk/Source/WebKit/Shared/RemoteRenderingBackendCreationParameters.h

    r271211 r271212  
    2828#if ENABLE(GPU_PROCESS)
    2929
    30 #include <WebCore/DisplayList.h>
    31 #include <WebCore/RenderingResourceIdentifier.h>
     30#include "RenderingBackendIdentifier.h"
     31#include <wtf/MachSendRight.h>
    3232
    3333namespace WebKit {
    3434
    35 struct GPUProcessWakeupMessageArguments {
    36     WebCore::DisplayList::ItemBufferIdentifier itemBufferIdentifier;
    37     uint64_t offset { 0 };
    38     WebCore::RenderingResourceIdentifier destinationImageBufferIdentifier;
     35struct RemoteRenderingBackendCreationParameters {
     36    RenderingBackendIdentifier identifier;
     37#if PLATFORM(COCOA)
     38    MachSendRight sendRightForResumeDisplayListSemaphore;
     39#endif
    3940
    4041    template<class Encoder> void encode(Encoder&) const;
    41     template<class Decoder> static Optional<GPUProcessWakeupMessageArguments> decode(Decoder&);
     42    template<class Decoder> static Optional<RemoteRenderingBackendCreationParameters> decode(Decoder&);
    4243};
    4344
    4445template<class Encoder>
    45 void GPUProcessWakeupMessageArguments::encode(Encoder& encoder) const
     46void RemoteRenderingBackendCreationParameters::encode(Encoder& encoder) const
    4647{
    47     encoder << itemBufferIdentifier;
    48     encoder << offset;
    49     encoder << destinationImageBufferIdentifier;
     48    encoder << identifier;
     49#if PLATFORM(COCOA)
     50    encoder << sendRightForResumeDisplayListSemaphore;
     51#endif
    5052}
    5153
    5254template<class Decoder>
    53 Optional<GPUProcessWakeupMessageArguments> GPUProcessWakeupMessageArguments::decode(Decoder& decoder)
     55Optional<RemoteRenderingBackendCreationParameters> RemoteRenderingBackendCreationParameters::decode(Decoder& decoder)
    5456{
    55     Optional<WebCore::DisplayList::ItemBufferIdentifier> itemBufferIdentifier;
    56     decoder >> itemBufferIdentifier;
    57     if (!itemBufferIdentifier)
     57    RemoteRenderingBackendCreationParameters parameters;
     58
     59    Optional<RenderingBackendIdentifier> identifier;
     60    decoder >> identifier;
     61    if (!identifier)
    5862        return WTF::nullopt;
    5963
    60     Optional<uint64_t> offset;
    61     decoder >> offset;
    62     if (!offset)
     64    parameters.identifier = *identifier;
     65
     66#if PLATFORM(COCOA)
     67    Optional<MachSendRight> sendRightForResumeDisplayListSemaphore;
     68    decoder >> sendRightForResumeDisplayListSemaphore;
     69    if (!sendRightForResumeDisplayListSemaphore)
    6370        return WTF::nullopt;
    6471
    65     Optional<WebCore::RenderingResourceIdentifier> destinationImageBufferIdentifier;
    66     decoder >> destinationImageBufferIdentifier;
    67     if (!destinationImageBufferIdentifier)
    68         return WTF::nullopt;
     72    parameters.sendRightForResumeDisplayListSemaphore = WTFMove(*sendRightForResumeDisplayListSemaphore);
     73#endif
    6974
    70     return {{ *itemBufferIdentifier, *offset, *destinationImageBufferIdentifier }};
     75    return parameters;
    7176}
    7277
  • trunk/Source/WebKit/Shared/SharedDisplayListHandle.h

    r270520 r271212  
    5656    virtual size_t advance(size_t amount) = 0;
    5757
     58    enum class WaitingStatus : uint8_t {
     59        NotWaiting,
     60        Waiting,
     61        Resuming
     62    };
     63
     64    struct ResumeReadingInformation {
     65        uint64_t offset;
     66        uint64_t destination;
     67    };
     68
    5869protected:
    5970    SharedDisplayListHandle(WebCore::DisplayList::ItemBufferIdentifier identifier, Ref<SharedMemory>&& sharedMemory)
     
    6879
    6980        Atomic<uint64_t> unreadBytes;
     81        ResumeReadingInformation resumeReadingInfo;
     82        Atomic<WaitingStatus> waitingStatus;
    7083    };
    7184
     85    const DisplayListSharedMemoryHeader& header() const { return *reinterpret_cast<const DisplayListSharedMemoryHeader*>(data()); }
    7286    DisplayListSharedMemoryHeader& header() { return *reinterpret_cast<DisplayListSharedMemoryHeader*>(data()); }
    7387
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r271207 r271212  
    19691969                F430E9422247335F005FE053 /* WebsiteMetaViewportPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = F430E941224732A9005FE053 /* WebsiteMetaViewportPolicy.h */; };
    19701970                F430E94422473DFF005FE053 /* WebContentMode.h in Headers */ = {isa = PBXBuildFile; fileRef = F430E94322473DB8005FE053 /* WebContentMode.h */; };
     1971                F437C8D92593B7E300DB8A1C /* RemoteRenderingBackendCreationParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = F437C8D82593B7E300DB8A1C /* RemoteRenderingBackendCreationParameters.h */; };
    19711972                F438CD1C2241421400DE6DDA /* WKWebpagePreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = F438CD1B224140A600DE6DDA /* WKWebpagePreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
    19721973                F438CD1F22414D4000DE6DDA /* WKWebpagePreferencesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = F438CD1E22414D4000DE6DDA /* WKWebpagePreferencesInternal.h */; };
     
    57785779                F430E941224732A9005FE053 /* WebsiteMetaViewportPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebsiteMetaViewportPolicy.h; sourceTree = "<group>"; };
    57795780                F430E94322473DB8005FE053 /* WebContentMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebContentMode.h; sourceTree = "<group>"; };
     5781                F437C8D82593B7E300DB8A1C /* RemoteRenderingBackendCreationParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteRenderingBackendCreationParameters.h; sourceTree = "<group>"; };
    57805782                F438CD1B224140A600DE6DDA /* WKWebpagePreferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKWebpagePreferences.h; sourceTree = "<group>"; };
    57815783                F438CD1D22414AD600DE6DDA /* WKWebpagePreferences.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebpagePreferences.mm; sourceTree = "<group>"; };
     
    65156517                                463FD4811EB94EAD00A2982C /* ProcessTerminationReason.h */,
    65166518                                9B1229D023FF2A5E008CA751 /* RemoteAudioDestinationIdentifier.h */,
     6519                                F437C8D82593B7E300DB8A1C /* RemoteRenderingBackendCreationParameters.h */,
    65176520                                5CB7AFE623C681B000E49CF3 /* ResourceLoadInfo.h */,
    65186521                                5C00993B2417FB7E00D53C25 /* ResourceLoadStatisticsParameters.h */,
     
    1184911852                                1AC1338018590AE400F3EC05 /* RemoteObjectRegistry.h in Headers */,
    1185011853                                1AC1338618590C4600F3EC05 /* RemoteObjectRegistryMessages.h in Headers */,
     11854                                F437C8D92593B7E300DB8A1C /* RemoteRenderingBackendCreationParameters.h in Headers */,
    1185111855                                0F594790187B3B3A00437857 /* RemoteScrollingCoordinator.h in Headers */,
    1185211856                                0F5947A8187B517600437857 /* RemoteScrollingCoordinatorMessages.h in Headers */,
  • trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.h

    r270478 r271212  
    4747    WebCore::DisplayList::ItemBufferHandle createHandle() const;
    4848
     49    bool tryToResume(SharedDisplayListHandle::ResumeReadingInformation&& info)
     50    {
     51        auto& header = this->header();
     52        header.resumeReadingInfo = WTFMove(info);
     53        return header.waitingStatus.compareExchangeWeak(SharedDisplayListHandle::WaitingStatus::Waiting, SharedDisplayListHandle::WaitingStatus::Resuming);
     54    }
     55
    4956private:
    5057    DisplayListWriterHandle(WebCore::DisplayList::ItemBufferIdentifier identifier, Ref<SharedMemory>&& sharedMemory)
  • trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp

    r271036 r271212  
    3333#include "ImageDataReference.h"
    3434#include "PlatformRemoteImageBufferProxy.h"
     35#include "RemoteRenderingBackendCreationParameters.h"
    3536#include "RemoteRenderingBackendMessages.h"
    3637#include "RemoteRenderingBackendProxyMessages.h"
     
    6768    connection.addClient(*this);
    6869    connection.messageReceiverMap().addMessageReceiver(Messages::RemoteRenderingBackendProxy::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this);
    69 
    70     send(Messages::GPUConnectionToWebProcess::CreateRenderingBackend(m_renderingBackendIdentifier), 0);
     70    send(Messages::GPUConnectionToWebProcess::CreateRenderingBackend({
     71        m_renderingBackendIdentifier,
     72#if PLATFORM(COCOA)
     73        m_resumeDisplayListSemaphore.createSendRight(),
     74#endif
     75    }), 0);
    7176}
    7277
     
    273278    bool wasEmpty = sharedHandle->advance(numberOfBytes) == numberOfBytes;
    274279    if (!wasEmpty || didChangeItemBuffer == DisplayList::DidChangeItemBuffer::Yes) {
    275         if (m_deferredWakeupMessageArguments && !--m_remainingItemsToAppendBeforeSendingWakeup)
    276             sendWakeupMessage(*std::exchange(m_deferredWakeupMessageArguments, WTF::nullopt));
    277         return;
    278     }
    279 
    280     sendDeferredWakeupMessageIfNeeded();
     280        if (m_deferredWakeupMessageArguments) {
     281            if (sharedHandle->tryToResume({ m_deferredWakeupMessageArguments->offset, m_deferredWakeupMessageArguments->destinationImageBufferIdentifier.toUInt64() })) {
     282#if PLATFORM(COCOA)
     283                m_resumeDisplayListSemaphore.signal();
     284#endif
     285                m_deferredWakeupMessageArguments = WTF::nullopt;
     286                m_remainingItemsToAppendBeforeSendingWakeup = 0;
     287            } else if (!--m_remainingItemsToAppendBeforeSendingWakeup) {
     288                m_deferredWakeupMessageArguments->reason = GPUProcessWakeupReason::ItemCountHysteresisExceeded;
     289                sendWakeupMessage(*std::exchange(m_deferredWakeupMessageArguments, WTF::nullopt));
     290            }
     291        }
     292        return;
     293    }
     294
     295    sendDeferredWakeupMessageIfNeeded();
     296
     297    auto offsetToRead = sharedHandle->writableOffset() - numberOfBytes;
     298    if (sharedHandle->tryToResume({ offsetToRead, destinationImageBuffer.toUInt64() })) {
     299#if PLATFORM(COCOA)
     300        m_resumeDisplayListSemaphore.signal();
     301#endif
     302        return;
     303    }
    281304
    282305    // Instead of sending the wakeup message immediately, wait for some additional data. This gives the
     
    286309
    287310    m_remainingItemsToAppendBeforeSendingWakeup = itemCountHysteresisBeforeSendingWakeup;
    288     m_deferredWakeupMessageArguments = {{
    289         handle.identifier,
    290         sharedHandle->writableOffset() - numberOfBytes,
    291         destinationImageBuffer
    292     }};
     311    m_deferredWakeupMessageArguments = {{ handle.identifier, offsetToRead, destinationImageBuffer }};
    293312}
    294313
  • trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h

    r271036 r271212  
    3939#include <wtf/Deque.h>
    4040#include <wtf/WeakPtr.h>
     41
     42#if PLATFORM(COCOA)
     43#include <wtf/cocoa/MachSemaphore.h>
     44#endif
    4145
    4246namespace WebCore {
     
    123127    Optional<GPUProcessWakeupMessageArguments> m_deferredWakeupMessageArguments;
    124128    unsigned m_remainingItemsToAppendBeforeSendingWakeup { 0 };
     129#if PLATFORM(COCOA)
     130    MachSemaphore m_resumeDisplayListSemaphore;
     131#endif
    125132};
    126133
Note: See TracChangeset for help on using the changeset viewer.