Commit 4f9ee5fb authored by Jonathan Backer's avatar Jonathan Backer Committed by Commit Bot

Implement raster context loss methods

Notable changes in this CL:

- mark all RasterDecoderImpl class final (maybe compiler can
  devirtualize)

- copy over context loss related methods from GLES2DecoderImpl to
  RasterDecoderImpl

- port over GLES2Decoder context loss unit tests to RasterDecoder

Bug: 789238
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I919163ce459603109b12ee864561debb136ff594
Reviewed-on: https://chromium-review.googlesource.com/1025961
Commit-Queue: Jonathan Backer <backer@chromium.org>
Reviewed-by: default avatarPeng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553538}
parent 52308ad8
......@@ -362,6 +362,7 @@ test("gpu_unittests") {
"command_buffer/service/raster_decoder_unittest_1.cc",
"command_buffer/service/raster_decoder_unittest_base.cc",
"command_buffer/service/raster_decoder_unittest_base.h",
"command_buffer/service/raster_decoder_unittest_context_lost.cc",
"command_buffer/service/renderbuffer_manager_unittest.cc",
"command_buffer/service/scheduler_unittest.cc",
"command_buffer/service/service_discardable_manager_unittest.cc",
......
......@@ -2,35 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gl_surface_mock.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_mock.h"
using ::gl::MockGLInterface;
using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::MatcherCast;
using ::testing::Mock;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SetArrayArgument;
using ::testing::SetArgPointee;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::StrictMock;
namespace gpu {
namespace gles2 {
......
......@@ -33,6 +33,7 @@
#include "gpu/command_buffer/common/raster_cmd_ids.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/decoder_client.h"
......@@ -237,7 +238,8 @@ ScopedPixelUnpackState::~ScopedPixelUnpackState() {
} // namespace
class RasterDecoderImpl : public RasterDecoder, public gles2::ErrorStateClient {
class RasterDecoderImpl final : public RasterDecoder,
public gles2::ErrorStateClient {
public:
RasterDecoderImpl(DecoderClient* client,
CommandBufferServiceBase* command_buffer_service,
......@@ -376,6 +378,11 @@ class RasterDecoderImpl : public RasterDecoder, public gles2::ErrorStateClient {
return feature_info_->workarounds();
}
bool IsRobustnessSupported() {
return has_robustness_extension_ &&
context_->WasAllocatedUsingRobustnessExtension();
}
const gl::GLVersionInfo& gl_version_info() {
return feature_info_->gl_version_info();
}
......@@ -621,6 +628,10 @@ class RasterDecoderImpl : public RasterDecoder, public gles2::ErrorStateClient {
bool supports_oop_raster_ = false;
bool has_robustness_extension_ = false;
bool context_was_lost_ = false;
bool reset_by_robustness_extension_ = false;
// The current decoder error communicates the decoder error through command
// processing functions that do not return the error value. Should be set
// only if not returning an error.
......@@ -662,6 +673,9 @@ class RasterDecoderImpl : public RasterDecoder, public gles2::ErrorStateClient {
bool gpu_debug_commands_;
// An optional behaviour to lose the context and group when OOM.
bool lose_context_when_out_of_memory_ = false;
// Log extra info.
bool service_logging_;
......@@ -787,6 +801,10 @@ ContextResult RasterDecoderImpl::Initialize(
surface_ = surface;
context_ = context;
// Save the loseContextWhenOutOfMemory context creation attribute.
lose_context_when_out_of_memory_ =
attrib_helper.lose_context_when_out_of_memory;
auto result =
group_->Initialize(this, attrib_helper.context_type, disallowed_features);
if (result != ContextResult::kSuccess) {
......@@ -838,6 +856,10 @@ ContextResult RasterDecoderImpl::Initialize(
api()->glActiveTextureFn(GL_TEXTURE0);
CHECK_GL_ERROR();
has_robustness_extension_ = features().arb_robustness ||
features().khr_robustness ||
features().ext_robustness;
// Set all the default state because some GL drivers get it wrong.
// TODO(backer): Not all of this state needs to be initialized. Reduce the set
// if perf becomes a problem.
......@@ -969,6 +991,13 @@ bool RasterDecoderImpl::MakeCurrent() {
}
DCHECK_EQ(api(), gl::g_current_gl_context);
if (CheckResetStatus()) {
LOG(ERROR)
<< " RasterDecoderImpl: Context reset detected after MakeCurrent.";
group_->LoseContexts(error::kUnknown);
return false;
}
// Rebind textures if the service ids may have changed.
RestoreAllExternalTextureBindingsIfNeeded();
......@@ -1170,20 +1199,65 @@ void RasterDecoderImpl::SetLevelInfo(uint32_t client_id,
}
bool RasterDecoderImpl::WasContextLost() const {
return false;
return context_was_lost_;
}
bool RasterDecoderImpl::WasContextLostByRobustnessExtension() const {
NOTIMPLEMENTED();
return false;
return WasContextLost() && reset_by_robustness_extension_;
}
void RasterDecoderImpl::MarkContextLost(error::ContextLostReason reason) {
NOTIMPLEMENTED();
// Only lose the context once.
if (WasContextLost())
return;
// Don't make GL calls in here, the context might not be current.
command_buffer_service()->SetContextLostReason(reason);
current_decoder_error_ = error::kLostContext;
context_was_lost_ = true;
if (vertex_array_manager_.get()) {
vertex_array_manager_->MarkContextLost();
}
state_.MarkContextLost();
}
bool RasterDecoderImpl::CheckResetStatus() {
NOTIMPLEMENTED();
DCHECK(!WasContextLost());
DCHECK(context_->IsCurrent(nullptr));
if (IsRobustnessSupported()) {
// If the reason for the call was a GL error, we can try to determine the
// reset status more accurately.
GLenum driver_status = api()->glGetGraphicsResetStatusARBFn();
if (driver_status == GL_NO_ERROR)
return false;
LOG(ERROR)
<< "RasterDecoder context lost via ARB/EXT_robustness. Reset status = "
<< GLES2Util::GetStringEnum(driver_status);
// Don't pretend we know which client was responsible.
if (workarounds().use_virtualized_gl_contexts)
driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
switch (driver_status) {
case GL_GUILTY_CONTEXT_RESET_ARB:
MarkContextLost(error::kGuilty);
break;
case GL_INNOCENT_CONTEXT_RESET_ARB:
MarkContextLost(error::kInnocent);
break;
case GL_UNKNOWN_CONTEXT_RESET_ARB:
MarkContextLost(error::kUnknown);
break;
default:
NOTREACHED();
return false;
}
reset_by_robustness_extension_ = true;
return true;
}
return false;
}
......@@ -1500,11 +1574,25 @@ ServiceTransferCache* RasterDecoderImpl::GetTransferCacheForTest() {
}
void RasterDecoderImpl::OnContextLostError() {
NOTIMPLEMENTED();
if (!WasContextLost()) {
// Need to lose current context before broadcasting!
CheckResetStatus();
group_->LoseContexts(error::kUnknown);
reset_by_robustness_extension_ = true;
}
}
void RasterDecoderImpl::OnOutOfMemoryError() {
NOTIMPLEMENTED();
if (lose_context_when_out_of_memory_ && !WasContextLost()) {
error::ContextLostReason other = error::kOutOfMemory;
if (CheckResetStatus()) {
other = error::kUnknown;
} else {
// Need to lose current context before broadcasting!
MarkContextLost(error::kOutOfMemory);
}
group_->LoseContexts(other);
}
}
error::Error RasterDecoderImpl::HandleWaitSyncTokenCHROMIUM(
......@@ -2471,7 +2559,7 @@ bool RasterDecoderImpl::DoBindOrCopyTexImageIfNeeded(Texture* texture,
namespace {
// Helper to read client data from transfer cache.
class TransferCacheDeserializeHelperImpl
class TransferCacheDeserializeHelperImpl final
: public cc::TransferCacheDeserializeHelper {
public:
explicit TransferCacheDeserializeHelperImpl(
......@@ -2479,12 +2567,12 @@ class TransferCacheDeserializeHelperImpl
: transfer_cache_(transfer_cache) {
DCHECK(transfer_cache_);
}
~TransferCacheDeserializeHelperImpl() final = default;
~TransferCacheDeserializeHelperImpl() override = default;
private:
cc::ServiceTransferCacheEntry* GetEntryInternal(
cc::TransferCacheEntryType entry_type,
uint32_t entry_id) final {
uint32_t entry_id) override {
return transfer_cache_->GetEntry(entry_type, entry_id);
}
ServiceTransferCache* const transfer_cache_;
......
......@@ -56,14 +56,6 @@ class RasterDecoderTest : public RasterDecoderTestBase {
RasterDecoderTest() = default;
};
class RasterDecoderManualInitTest : public RasterDecoderTestBase {
public:
RasterDecoderManualInitTest() = default;
// Override default setup so nothing gets setup.
void SetUp() override {}
};
INSTANTIATE_TEST_CASE_P(Service, RasterDecoderTest, ::testing::Bool());
INSTANTIATE_TEST_CASE_P(Service,
RasterDecoderManualInitTest,
......@@ -251,7 +243,10 @@ TEST_P(RasterDecoderTest, TexStorage2D) {
}
TEST_P(RasterDecoderManualInitTest, TexStorage2DWithEXTTextureStorage) {
InitDecoderWithWorkarounds({"GL_ARB_sync", "GL_EXT_texture_storage"});
InitState init;
init.extensions.push_back("GL_EXT_texture_storage");
InitDecoder(init);
DoTexStorage2D(client_texture_id_, 2 /* levels */, kWidth, kHeight);
gles2::TextureRef* texture_ref =
......@@ -277,7 +272,8 @@ TEST_P(RasterDecoderManualInitTest, TexStorage2DWithEXTTextureStorage) {
TEST_P(RasterDecoderManualInitTest, TexStorage2DOutOfMemory) {
scoped_refptr<MockMemoryTracker> memory_tracker = new MockMemoryTracker();
set_memory_tracker(memory_tracker.get());
InitDecoderWithWorkarounds({"GL_ARB_sync"});
InitDecoder(InitState());
EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(_))
.WillOnce(Return(false))
......
......@@ -48,10 +48,13 @@ using namespace gpu::gles2;
namespace gpu {
namespace raster {
RasterDecoderTestBase::InitState::InitState() = default;
RasterDecoderTestBase::InitState::~InitState() = default;
RasterDecoderTestBase::RasterDecoderTestBase()
: surface_(NULL),
context_(NULL),
memory_tracker_(NULL),
: surface_(nullptr),
context_(nullptr),
memory_tracker_(nullptr),
client_texture_id_(106),
shared_memory_id_(0),
shared_memory_offset_(0),
......@@ -77,7 +80,7 @@ void RasterDecoderTestBase::OnDescheduleUntilFinished() {}
void RasterDecoderTestBase::OnRescheduleAfterFinished() {}
void RasterDecoderTestBase::SetUp() {
InitDecoderWithWorkarounds({"GL_ARB_sync"});
InitDecoder(InitState());
}
void RasterDecoderTestBase::AddExpectationsForVertexAttribManager() {
......@@ -164,15 +167,13 @@ void RasterDecoderTestBase::ExpectEnableDisable(GLenum cap, bool enable) {
}
}
void RasterDecoderTestBase::InitDecoderWithWorkarounds(
std::initializer_list<std::string> extensions) {
void RasterDecoderTestBase::InitDecoder(const InitState& init) {
std::string all_extensions;
for (const std::string& extension : extensions) {
for (const std::string& extension : init.extensions) {
all_extensions += extension + " ";
}
const std::string gl_version("2.1");
const bool bind_generates_resource(false);
const bool lose_context_when_out_of_memory(false);
const ContextType context_type(CONTEXT_TYPE_OPENGLES2);
// For easier substring/extension matching
......@@ -182,8 +183,7 @@ void RasterDecoderTestBase::InitDecoderWithWorkarounds(
gl_.reset(new StrictMock<MockGLInterface>());
::gl::MockGLInterface::SetGLInterface(gl_.get());
gpu::GpuDriverBugWorkarounds workarounds;
scoped_refptr<FeatureInfo> feature_info = new FeatureInfo(workarounds);
scoped_refptr<FeatureInfo> feature_info = new FeatureInfo(init.workarounds);
group_ = scoped_refptr<ContextGroup>(new ContextGroup(
gpu_preferences_, false, &mailbox_manager_, memory_tracker_,
......@@ -229,7 +229,8 @@ void RasterDecoderTestBase::InitDecoderWithWorkarounds(
ClearSharedMemory();
ContextCreationAttribs attribs;
attribs.lose_context_when_out_of_memory = lose_context_when_out_of_memory;
attribs.lose_context_when_out_of_memory =
init.lose_context_when_out_of_memory;
attribs.context_type = context_type;
if (group_->feature_info()->feature_flags().native_vertex_array_object) {
......@@ -311,7 +312,7 @@ void RasterDecoderTestBase::ResetDecoder() {
decoder_.reset();
group_->Destroy(mock_decoder_.get(), false);
command_buffer_service_.reset();
::gl::MockGLInterface::SetGLInterface(NULL);
::gl::MockGLInterface::SetGLInterface(nullptr);
gl_.reset();
gl::init::ShutdownGL(false);
}
......
......@@ -12,6 +12,7 @@
#include <initializer_list>
#include <memory>
#include <string>
#include <vector>
#include "base/message_loop/message_loop.h"
#include "gpu/command_buffer/client/client_test_helper.h"
......@@ -139,9 +140,16 @@ class RasterDecoderTestBase : public ::testing::TestWithParam<bool>,
void AddExpectationsForBindVertexArrayOES();
void AddExpectationsForRestoreAttribState(GLuint attrib);
void InitDecoderWithWorkarounds(
std::initializer_list<std::string> extensions);
struct InitState {
InitState();
~InitState();
std::vector<std::string> extensions = {"GL_ARB_sync"};
bool lose_context_when_out_of_memory = false;
gpu::GpuDriverBugWorkarounds workarounds;
};
void InitDecoder(const InitState& init);
void ResetDecoder();
const gles2::ContextGroup& group() const { return *group_.get(); }
......@@ -264,6 +272,14 @@ class RasterDecoderTestBase : public ::testing::TestWithParam<bool>,
gles2::MockCopyTextureResourceManager* copy_texture_manager_; // not owned
};
class RasterDecoderManualInitTest : public RasterDecoderTestBase {
public:
RasterDecoderManualInitTest() = default;
// Override default setup so nothing gets setup.
void SetUp() override {}
};
} // namespace raster
} // namespace gpu
......
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