Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(729)

Unified Diff: gpu/ipc/client/command_buffer_proxy_impl.cc

Issue 1916303003: Report lost context from GLES2Implementation based on share group state. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: lost-share-group: disconnect-channel Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/ipc/client/command_buffer_proxy_impl.h ('k') | mojo/gles2/command_buffer_client_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/ipc/client/command_buffer_proxy_impl.cc
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc
index ddd9d005a6b907c2125a41df4b22d3254b839bdd..1dff246170192994639694f7d74bb16b1b6de236 100644
--- a/gpu/ipc/client/command_buffer_proxy_impl.cc
+++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
+#include "base/optional.h"
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -85,8 +86,9 @@ bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
IPC_END_MESSAGE_MAP()
if (!handled) {
- DLOG(ERROR) << "Gpu process sent invalid message.";
- InvalidGpuMessage();
+ LOG(ERROR) << "Gpu process sent invalid message.";
+ OnGpuAsyncMessageError(gpu::error::kInvalidGpuMessage,
+ gpu::error::kLostContext);
}
return handled;
}
@@ -99,32 +101,18 @@ void CommandBufferProxyImpl::OnChannelError() {
gpu::error::ContextLostReason context_lost_reason =
gpu::error::kGpuChannelLost;
if (shared_state_shm_ && shared_state_shm_->memory()) {
- TryUpdateState();
// The GPU process might have intentionally been crashed
// (exit_on_context_lost), so try to find out the original reason.
+ TryUpdateStateDontReportError();
if (last_state_.error == gpu::error::kLostContext)
context_lost_reason = last_state_.context_lost_reason;
}
- OnDestroyed(context_lost_reason, gpu::error::kLostContext);
+ OnGpuAsyncMessageError(context_lost_reason, gpu::error::kLostContext);
}
void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason,
gpu::error::Error error) {
- CheckLock();
-
- // When the client sees that the context is lost, they should delete this
- // CommandBufferProxyImpl and create a new one.
- last_state_.error = error;
- last_state_.context_lost_reason = reason;
-
- // Prevent any further messages from being sent, and ensure we only call
- // the client for lost context a single time.
- if (channel_) {
- channel_->DestroyCommandBuffer(this);
- channel_ = nullptr;
- if (gpu_control_client_)
- gpu_control_client_->OnGpuControlLostContext();
- }
+ OnGpuAsyncMessageError(reason, error);
}
void CommandBufferProxyImpl::OnConsoleMessage(
@@ -152,8 +140,9 @@ void CommandBufferProxyImpl::RemoveDeletionObserver(
void CommandBufferProxyImpl::OnSignalAck(uint32_t id) {
SignalTaskMap::iterator it = signal_tasks_.find(id);
if (it == signal_tasks_.end()) {
- DLOG(ERROR) << "Gpu process sent invalid SignalAck.";
- InvalidGpuMessage();
+ LOG(ERROR) << "Gpu process sent invalid SignalAck.";
+ OnGpuAsyncMessageError(gpu::error::kInvalidGpuMessage,
+ gpu::error::kLostContext);
return;
}
base::Closure callback = it->second;
@@ -297,12 +286,12 @@ void CommandBufferProxyImpl::WaitForTokenInRange(int32_t start, int32_t end) {
gpu::CommandBuffer::State state;
if (Send(new GpuCommandBufferMsg_WaitForTokenInRange(route_id_, start, end,
&state)))
- OnUpdateState(state);
+ SetStateFromSyncReply(state);
}
if (!InRange(start, end, last_state_.token) &&
last_state_.error == gpu::error::kNoError) {
- DLOG(ERROR) << "GPU state invalid after WaitForTokenInRange.";
- InvalidGpuReply();
+ LOG(ERROR) << "GPU state invalid after WaitForTokenInRange.";
+ OnGpuSyncReplyError();
}
}
@@ -317,12 +306,12 @@ void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32_t start,
gpu::CommandBuffer::State state;
if (Send(new GpuCommandBufferMsg_WaitForGetOffsetInRange(route_id_, start,
end, &state)))
- OnUpdateState(state);
+ SetStateFromSyncReply(state);
}
if (!InRange(start, end, last_state_.get_offset) &&
last_state_.error == gpu::error::kNoError) {
- DLOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange.";
- InvalidGpuReply();
+ LOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange.";
+ OnGpuSyncReplyError();
}
}
@@ -350,14 +339,14 @@ scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
channel_->factory()->AllocateSharedMemory(size));
if (!shared_memory) {
if (last_state_.error == gpu::error::kNoError)
- last_state_.error = gpu::error::kOutOfBounds;
+ OnClientError(gpu::error::kOutOfBounds);
return NULL;
}
DCHECK(!shared_memory->memory());
if (!shared_memory->Map(size)) {
if (last_state_.error == gpu::error::kNoError)
- last_state_.error = gpu::error::kOutOfBounds;
+ OnClientError(gpu::error::kOutOfBounds);
return NULL;
}
@@ -368,7 +357,7 @@ scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
channel_->ShareToGpuProcess(shared_memory->handle());
if (!base::SharedMemory::IsHandleValid(handle)) {
if (last_state_.error == gpu::error::kNoError)
- last_state_.error = gpu::error::kLostContext;
+ OnClientError(gpu::error::kLostContext);
return NULL;
}
@@ -506,10 +495,6 @@ void CommandBufferProxyImpl::SetLock(base::Lock* lock) {
lock_ = lock;
}
-bool CommandBufferProxyImpl::IsGpuChannelLost() {
- return !channel_ || channel_->IsLost();
-}
-
void CommandBufferProxyImpl::EnsureWorkVisible() {
if (channel_)
channel_->ValidateFlushIDReachedServer(stream_id_, true);
@@ -649,19 +634,30 @@ bool CommandBufferProxyImpl::Send(IPC::Message* msg) {
// OnChannelError is called after returning to the message loop in case
// it is referenced elsewhere.
DVLOG(1) << "CommandBufferProxyImpl::Send failed. Losing context.";
- last_state_.error = gpu::error::kLostContext;
+ OnClientError(gpu::error::kLostContext);
return false;
}
-void CommandBufferProxyImpl::OnUpdateState(
+void CommandBufferProxyImpl::SetStateFromSyncReply(
const gpu::CommandBuffer::State& state) {
+ DCHECK(last_state_.error == gpu::error::kNoError);
// Handle wraparound. It works as long as we don't have more than 2B state
// updates in flight across which reordering occurs.
if (state.generation - last_state_.generation < 0x80000000U)
last_state_ = state;
+ if (last_state_.error != gpu::error::kNoError)
+ OnGpuStateError();
}
void CommandBufferProxyImpl::TryUpdateState() {
+ if (last_state_.error == gpu::error::kNoError) {
+ shared_state()->Read(&last_state_);
+ if (last_state_.error != gpu::error::kNoError)
+ OnGpuStateError();
+ }
+}
+
+void CommandBufferProxyImpl::TryUpdateStateDontReportError() {
if (last_state_.error == gpu::error::kNoError)
shared_state()->Read(&last_state_);
}
@@ -702,27 +698,75 @@ void CommandBufferProxyImpl::OnUpdateVSyncParameters(base::TimeTicks timebase,
update_vsync_parameters_completion_callback_.Run(timebase, interval);
}
-void CommandBufferProxyImpl::InvalidGpuMessage() {
- LOG(ERROR) << "Received invalid message from the GPU process.";
- OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext);
+void CommandBufferProxyImpl::OnGpuSyncReplyError() {
+ last_state_.error = gpu::error::kLostContext;
+ last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage;
+ // This method may be inside a callstack from the GpuControlClient (we got a
+ // bad reply to something we are sending to the GPU process). So avoid
+ // re-entering the GpuControlClient here.
+ DisconnectChannelInFreshCallStack();
}
-void CommandBufferProxyImpl::InvalidGpuReply() {
+void CommandBufferProxyImpl::OnGpuAsyncMessageError(
+ gpu::error::ContextLostReason reason,
+ gpu::error::Error error) {
CheckLock();
- LOG(ERROR) << "Received invalid reply from the GPU process.";
- last_state_.error = gpu::error::kLostContext;
- last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage;
+ last_state_.error = error;
+ last_state_.context_lost_reason = reason;
+ // This method only occurs when receiving IPC messages, so we know it's not in
+ // a callstack from the GpuControlClient.
+ DisconnectChannel();
+}
+
+void CommandBufferProxyImpl::OnGpuStateError() {
+ DCHECK(last_state_.error != gpu::error::kNoError);
+ // This method may be inside a callstack from the GpuControlClient (we
+ // encountered an error while trying to perform some action). So avoid
+ // re-entering the GpuControlClient here.
+ DisconnectChannelInFreshCallStack();
+}
+
+void CommandBufferProxyImpl::OnClientError(gpu::error::Error error) {
+ CheckLock();
+ last_state_.error = error;
+ last_state_.context_lost_reason = gpu::error::kUnknown;
+ // This method may be inside a callstack from the GpuControlClient (we
+ // encountered an error while trying to perform some action). So avoid
+ // re-entering the GpuControlClient here.
+ DisconnectChannelInFreshCallStack();
+}
+
+void CommandBufferProxyImpl::DisconnectChannelInFreshCallStack() {
+ CheckLock();
+ // Inform the GpuControlClient of the lost state immediately, though this may
+ // be a re-entrant call to the client so we use the MaybeReentrant variant.
+ if (gpu_control_client_)
+ gpu_control_client_->OnGpuControlLostContextMaybeReentrant();
+ // Create a fresh call stack to keep the |channel_| alive while we unwind the
+ // stack in case things will use it, and give the GpuChannelClient a chance to
+ // act fully on the lost context.
callback_thread_->PostTask(
- FROM_HERE,
- base::Bind(&CommandBufferProxyImpl::InvalidGpuReplyOnClientThread,
- weak_this_));
+ FROM_HERE, base::Bind(&CommandBufferProxyImpl::LockAndDisconnectChannel,
+ weak_this_));
}
-void CommandBufferProxyImpl::InvalidGpuReplyOnClientThread() {
- std::unique_ptr<base::AutoLock> lock;
+void CommandBufferProxyImpl::LockAndDisconnectChannel() {
+ base::Optional<base::AutoLock> hold;
if (lock_)
- lock.reset(new base::AutoLock(*lock_));
- OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext);
+ hold.emplace(*lock_);
+ DisconnectChannel();
+}
+
+void CommandBufferProxyImpl::DisconnectChannel() {
+ CheckLock();
+ // Prevent any further messages from being sent, and ensure we only call
+ // the client for lost context a single time.
+ if (!channel_)
+ return;
+ channel_->DestroyCommandBuffer(this);
+ channel_ = nullptr;
+ if (gpu_control_client_)
+ gpu_control_client_->OnGpuControlLostContext();
}
} // namespace gpu
« no previous file with comments | « gpu/ipc/client/command_buffer_proxy_impl.h ('k') | mojo/gles2/command_buffer_client_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698