Commit c97b35ae authored by Eric Karl's avatar Eric Karl Committed by Commit Bot

Handle context loss + gpu:buffer creation failure in Discardable system

If we lose our context (or potentially in rare OOM cases), gpu::buffer
allocation can fail. In these cases the discardable system shouldn't
crash, but should fail gracefully.

Bug: 762645
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I9d56536fd21893689ef993a68ee2a5639947e612
Reviewed-on: https://chromium-review.googlesource.com/782647Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Commit-Queue: Eric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519763}
parent 20decfe2
...@@ -140,7 +140,11 @@ ClientDiscardableHandle::Id ClientDiscardableManager::CreateHandle( ...@@ -140,7 +140,11 @@ ClientDiscardableHandle::Id ClientDiscardableManager::CreateHandle(
scoped_refptr<Buffer> buffer; scoped_refptr<Buffer> buffer;
int32_t shm_id; int32_t shm_id;
uint32_t offset = 0; uint32_t offset = 0;
FindAllocation(command_buffer, &buffer, &shm_id, &offset); if (!FindAllocation(command_buffer, &buffer, &shm_id, &offset)) {
// This can fail if we've lost context, return an invalid Id.
return ClientDiscardableHandle::Id();
}
DCHECK_LT(offset * element_size_, std::numeric_limits<uint32_t>::max()); DCHECK_LT(offset * element_size_, std::numeric_limits<uint32_t>::max());
uint32_t byte_offset = static_cast<uint32_t>(offset * element_size_); uint32_t byte_offset = static_cast<uint32_t>(offset * element_size_);
ClientDiscardableHandle handle(std::move(buffer), byte_offset, shm_id); ClientDiscardableHandle handle(std::move(buffer), byte_offset, shm_id);
...@@ -178,7 +182,7 @@ ClientDiscardableHandle ClientDiscardableManager::GetHandle( ...@@ -178,7 +182,7 @@ ClientDiscardableHandle ClientDiscardableManager::GetHandle(
return found->second; return found->second;
} }
void ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer, bool ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer,
scoped_refptr<Buffer>* buffer, scoped_refptr<Buffer>* buffer,
int32_t* shm_id, int32_t* shm_id,
uint32_t* offset) { uint32_t* offset) {
...@@ -191,18 +195,21 @@ void ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer, ...@@ -191,18 +195,21 @@ void ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer,
*offset = allocation->free_offsets.TakeFreeOffset(); *offset = allocation->free_offsets.TakeFreeOffset();
*shm_id = allocation->shm_id; *shm_id = allocation->shm_id;
*buffer = allocation->buffer; *buffer = allocation->buffer;
return; return true;
} }
// We couldn't find an existing free entry. Allocate more space. // We couldn't find an existing free entry. Allocate more space.
auto allocation = std::make_unique<Allocation>(elements_per_allocation_); auto allocation = std::make_unique<Allocation>(elements_per_allocation_);
allocation->buffer = command_buffer->CreateTransferBuffer( allocation->buffer = command_buffer->CreateTransferBuffer(
allocation_size_, &allocation->shm_id); allocation_size_, &allocation->shm_id);
if (!allocation->buffer)
return false;
*offset = allocation->free_offsets.TakeFreeOffset(); *offset = allocation->free_offsets.TakeFreeOffset();
*shm_id = allocation->shm_id; *shm_id = allocation->shm_id;
*buffer = allocation->buffer; *buffer = allocation->buffer;
allocations_.push_back(std::move(allocation)); allocations_.push_back(std::move(allocation));
return true;
} }
void ClientDiscardableManager::ReturnAllocation( void ClientDiscardableManager::ReturnAllocation(
......
...@@ -38,7 +38,7 @@ class GPU_EXPORT ClientDiscardableManager { ...@@ -38,7 +38,7 @@ class GPU_EXPORT ClientDiscardableManager {
} }
private: private:
void FindAllocation(CommandBuffer* command_buffer, bool FindAllocation(CommandBuffer* command_buffer,
scoped_refptr<Buffer>* buffer, scoped_refptr<Buffer>* buffer,
int32_t* shm_id, int32_t* shm_id,
uint32_t* offset); uint32_t* offset);
......
...@@ -16,6 +16,9 @@ ClientDiscardableHandle ClientDiscardableTextureManager::InitializeTexture( ...@@ -16,6 +16,9 @@ ClientDiscardableHandle ClientDiscardableTextureManager::InitializeTexture(
texture_id_to_handle_id_.end()); texture_id_to_handle_id_.end());
ClientDiscardableHandle::Id handle_id = ClientDiscardableHandle::Id handle_id =
discardable_manager_.CreateHandle(command_buffer); discardable_manager_.CreateHandle(command_buffer);
if (handle_id.is_null())
return ClientDiscardableHandle();
texture_id_to_handle_id_[texture_id] = handle_id; texture_id_to_handle_id_[texture_id] = handle_id;
return discardable_manager_.GetHandle(handle_id); return discardable_manager_.GetHandle(handle_id);
} }
......
...@@ -7075,6 +7075,9 @@ void GLES2Implementation::InitializeDiscardableTextureCHROMIUM( ...@@ -7075,6 +7075,9 @@ void GLES2Implementation::InitializeDiscardableTextureCHROMIUM(
} }
ClientDiscardableHandle handle = ClientDiscardableHandle handle =
manager->InitializeTexture(helper_->command_buffer(), texture_id); manager->InitializeTexture(helper_->command_buffer(), texture_id);
if (!handle.IsValid())
return;
helper_->InitializeDiscardableTextureCHROMIUM(texture_id, handle.shm_id(), helper_->InitializeDiscardableTextureCHROMIUM(texture_id, handle.shm_id(),
handle.byte_offset()); handle.byte_offset());
} }
......
...@@ -59,6 +59,9 @@ volatile base::subtle::Atomic32* DiscardableHandleBase::AsAtomic() const { ...@@ -59,6 +59,9 @@ volatile base::subtle::Atomic32* DiscardableHandleBase::AsAtomic() const {
buffer_->GetDataAddress(byte_offset_, sizeof(base::subtle::Atomic32))); buffer_->GetDataAddress(byte_offset_, sizeof(base::subtle::Atomic32)));
} }
ClientDiscardableHandle::ClientDiscardableHandle()
: DiscardableHandleBase(nullptr, 0, 0) {}
ClientDiscardableHandle::ClientDiscardableHandle(scoped_refptr<Buffer> buffer, ClientDiscardableHandle::ClientDiscardableHandle(scoped_refptr<Buffer> buffer,
uint32_t byte_offset, uint32_t byte_offset,
int32_t shm_id) int32_t shm_id)
......
...@@ -71,6 +71,7 @@ class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase { ...@@ -71,6 +71,7 @@ class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase {
uint64_t, uint64_t,
std::numeric_limits<uint64_t>::max()>; std::numeric_limits<uint64_t>::max()>;
ClientDiscardableHandle(); // Constructs an invalid handle.
ClientDiscardableHandle(scoped_refptr<Buffer> buffer, ClientDiscardableHandle(scoped_refptr<Buffer> buffer,
uint32_t byte_offset, uint32_t byte_offset,
int32_t shm_id); int32_t shm_id);
...@@ -90,6 +91,8 @@ class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase { ...@@ -90,6 +91,8 @@ class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase {
// Gets an Id which uniquely identifies this ClientDiscardableHandle within // Gets an Id which uniquely identifies this ClientDiscardableHandle within
// the ClientDiscardableManager which created it. // the ClientDiscardableManager which created it.
Id GetId() const; Id GetId() const;
bool IsValid() const { return !GetId().is_null(); }
}; };
// ServiceDiscardableHandle can wrap an existing handle (via the constructor), // ServiceDiscardableHandle can wrap an existing handle (via the constructor),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment