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(
scoped_refptr<Buffer> buffer;
int32_t shm_id;
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());
uint32_t byte_offset = static_cast<uint32_t>(offset * element_size_);
ClientDiscardableHandle handle(std::move(buffer), byte_offset, shm_id);
......@@ -178,7 +182,7 @@ ClientDiscardableHandle ClientDiscardableManager::GetHandle(
return found->second;
}
void ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer,
bool ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer,
scoped_refptr<Buffer>* buffer,
int32_t* shm_id,
uint32_t* offset) {
......@@ -191,18 +195,21 @@ void ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer,
*offset = allocation->free_offsets.TakeFreeOffset();
*shm_id = allocation->shm_id;
*buffer = allocation->buffer;
return;
return true;
}
// We couldn't find an existing free entry. Allocate more space.
auto allocation = std::make_unique<Allocation>(elements_per_allocation_);
allocation->buffer = command_buffer->CreateTransferBuffer(
allocation_size_, &allocation->shm_id);
if (!allocation->buffer)
return false;
*offset = allocation->free_offsets.TakeFreeOffset();
*shm_id = allocation->shm_id;
*buffer = allocation->buffer;
allocations_.push_back(std::move(allocation));
return true;
}
void ClientDiscardableManager::ReturnAllocation(
......
......@@ -38,7 +38,7 @@ class GPU_EXPORT ClientDiscardableManager {
}
private:
void FindAllocation(CommandBuffer* command_buffer,
bool FindAllocation(CommandBuffer* command_buffer,
scoped_refptr<Buffer>* buffer,
int32_t* shm_id,
uint32_t* offset);
......
......@@ -16,6 +16,9 @@ ClientDiscardableHandle ClientDiscardableTextureManager::InitializeTexture(
texture_id_to_handle_id_.end());
ClientDiscardableHandle::Id handle_id =
discardable_manager_.CreateHandle(command_buffer);
if (handle_id.is_null())
return ClientDiscardableHandle();
texture_id_to_handle_id_[texture_id] = handle_id;
return discardable_manager_.GetHandle(handle_id);
}
......
......@@ -7075,6 +7075,9 @@ void GLES2Implementation::InitializeDiscardableTextureCHROMIUM(
}
ClientDiscardableHandle handle =
manager->InitializeTexture(helper_->command_buffer(), texture_id);
if (!handle.IsValid())
return;
helper_->InitializeDiscardableTextureCHROMIUM(texture_id, handle.shm_id(),
handle.byte_offset());
}
......
......@@ -59,6 +59,9 @@ volatile base::subtle::Atomic32* DiscardableHandleBase::AsAtomic() const {
buffer_->GetDataAddress(byte_offset_, sizeof(base::subtle::Atomic32)));
}
ClientDiscardableHandle::ClientDiscardableHandle()
: DiscardableHandleBase(nullptr, 0, 0) {}
ClientDiscardableHandle::ClientDiscardableHandle(scoped_refptr<Buffer> buffer,
uint32_t byte_offset,
int32_t shm_id)
......
......@@ -71,6 +71,7 @@ class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase {
uint64_t,
std::numeric_limits<uint64_t>::max()>;
ClientDiscardableHandle(); // Constructs an invalid handle.
ClientDiscardableHandle(scoped_refptr<Buffer> buffer,
uint32_t byte_offset,
int32_t shm_id);
......@@ -90,6 +91,8 @@ class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase {
// Gets an Id which uniquely identifies this ClientDiscardableHandle within
// the ClientDiscardableManager which created it.
Id GetId() const;
bool IsValid() const { return !GetId().is_null(); }
};
// 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