Commit db2d4ad7 authored by Khushal's avatar Khushal Committed by Commit Bot

gpu: Share GrContext between RasterDecoders for OOP raster.

Use a common GrContext across all RasterDecoders. This ensures that we
get a unified GrProgramCache for compiled shaders.

R=backer@chromium.org, ericrk@chromium.org

Bug: 854416
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: I653486d2a20f4bb0112c6cfe66f3922c222ad338
Reviewed-on: https://chromium-review.googlesource.com/1114287
Commit-Queue: Khushal <khushalsagar@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#572377}
parent d7209bb8
...@@ -480,6 +480,7 @@ test("gpu_unittests") { ...@@ -480,6 +480,7 @@ test("gpu_unittests") {
"//testing/gtest", "//testing/gtest",
"//third_party/angle:translator", "//third_party/angle:translator",
"//third_party/mesa:mesa_headers", "//third_party/mesa:mesa_headers",
"//third_party/mesa:osmesa",
"//ui/gfx", "//ui/gfx",
"//ui/gfx:test_support", "//ui/gfx:test_support",
"//ui/gfx/geometry", "//ui/gfx/geometry",
...@@ -525,6 +526,7 @@ test("gpu_perftests") { ...@@ -525,6 +526,7 @@ test("gpu_perftests") {
data_deps = [ data_deps = [
# Needed for isolate script to execute. # Needed for isolate script to execute.
"//testing:run_perf_test", "//testing:run_perf_test",
"//third_party/mesa:osmesa",
] ]
# This target should not require the Chrome executable to run. # This target should not require the Chrome executable to run.
......
...@@ -191,6 +191,8 @@ target(link_target_type, "gles2_sources") { ...@@ -191,6 +191,8 @@ target(link_target_type, "gles2_sources") {
"raster_cmd_validation_implementation_autogen.h", "raster_cmd_validation_implementation_autogen.h",
"raster_decoder.cc", "raster_decoder.cc",
"raster_decoder.h", "raster_decoder.h",
"raster_decoder_context_state.cc",
"raster_decoder_context_state.h",
"renderbuffer_manager.cc", "renderbuffer_manager.cc",
"renderbuffer_manager.h", "renderbuffer_manager.h",
"sampler_manager.cc", "sampler_manager.cc",
......
...@@ -24,16 +24,19 @@ class Outputter; ...@@ -24,16 +24,19 @@ class Outputter;
} // namespace gles2 } // namespace gles2
namespace raster { namespace raster {
struct RasterDecoderContextState;
// This class implements the AsyncAPIInterface interface, decoding // This class implements the AsyncAPIInterface interface, decoding
// RasterInterface commands and calling GL. // RasterInterface commands and calling GL.
class GPU_GLES2_EXPORT RasterDecoder : public DecoderContext, class GPU_GLES2_EXPORT RasterDecoder : public DecoderContext,
public CommonDecoder { public CommonDecoder {
public: public:
static RasterDecoder* Create(DecoderClient* client, static RasterDecoder* Create(
CommandBufferServiceBase* command_buffer_service, DecoderClient* client,
gles2::Outputter* outputter, CommandBufferServiceBase* command_buffer_service,
gles2::ContextGroup* group); gles2::Outputter* outputter,
gles2::ContextGroup* group,
scoped_refptr<RasterDecoderContextState> raster_decoder_context_state);
~RasterDecoder() override; ~RasterDecoder() override;
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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/raster_decoder_context_state.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/create_gr_gl_interface.h"
namespace gpu {
namespace raster {
RasterDecoderContextState::RasterDecoderContextState(
scoped_refptr<gl::GLShareGroup> share_group,
scoped_refptr<gl::GLSurface> surface,
scoped_refptr<gl::GLContext> context,
bool use_virtualized_gl_contexts)
: share_group(std::move(share_group)),
surface(std::move(surface)),
context(std::move(context)),
use_virtualized_gl_contexts(use_virtualized_gl_contexts) {}
RasterDecoderContextState::~RasterDecoderContextState() {
if (gr_context)
gr_context->abandonContext();
}
void RasterDecoderContextState::InitializeGrContext(
const GpuDriverBugWorkarounds& workarounds) {
DCHECK(context->IsCurrent(surface.get()));
sk_sp<const GrGLInterface> interface(
gl::init::CreateGrGLInterface(*context->GetVersionInfo()));
if (!interface) {
LOG(ERROR) << "OOP raster support disabled: GrGLInterface creation "
"failed.";
return;
}
// If you make any changes to the GrContext::Options here that could
// affect text rendering, make sure to match the capabilities initialized
// in GetCapabilities and ensuring these are also used by the
// PaintOpBufferSerializer.
GrContextOptions options;
options.fDriverBugWorkarounds =
GrDriverBugWorkarounds(workarounds.ToIntSet());
size_t max_resource_cache_bytes = 0u;
raster::DetermineGrCacheLimitsFromAvailableMemory(
&max_resource_cache_bytes, &glyph_cache_max_texture_bytes);
options.fGlyphCacheTextureMaximumBytes = glyph_cache_max_texture_bytes;
gr_context = GrContext::MakeGL(std::move(interface), options);
if (!gr_context) {
LOG(ERROR) << "OOP raster support disabled: GrContext creation "
"failed.";
} else {
constexpr int kMaxGaneshResourceCacheCount = 16384;
gr_context->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
max_resource_cache_bytes);
}
}
} // namespace raster
} // namespace gpu
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_SERVICE_RASTER_DECODER_CONTEXT_STATE_H_
#define GPU_COMMAND_BUFFER_SERVICE_RASTER_DECODER_CONTEXT_STATE_H_
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/common/skia_utils.h"
#include "gpu/gpu_gles2_export.h"
#include "third_party/skia/include/gpu/GrContext.h"
namespace gl {
class GLContext;
class GLShareGroup;
class GLSurface;
} // namespace gl
namespace gpu {
class GpuDriverBugWorkarounds;
namespace raster {
struct GPU_GLES2_EXPORT RasterDecoderContextState
: public base::RefCounted<RasterDecoderContextState> {
public:
RasterDecoderContextState(scoped_refptr<gl::GLShareGroup> share_group,
scoped_refptr<gl::GLSurface> surface,
scoped_refptr<gl::GLContext> context,
bool use_virtualized_gl_contexts);
void InitializeGrContext(const GpuDriverBugWorkarounds& workarounds);
scoped_refptr<gl::GLShareGroup> share_group;
scoped_refptr<gl::GLSurface> surface;
scoped_refptr<gl::GLContext> context;
sk_sp<GrContext> gr_context;
bool use_virtualized_gl_contexts = false;
bool context_lost = false;
size_t glyph_cache_max_texture_bytes = 0u;
// |need_context_state_reset| is set whenever Skia may have altered the
// driver's GL state. It signals the need to restore driver GL state to
// |state_| before executing commands that do not
// PermitsInconsistentContextState.
bool need_context_state_reset = false;
private:
friend class base::RefCounted<RasterDecoderContextState>;
~RasterDecoderContextState();
};
} // namespace raster
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_RASTER_DECODER_CONTEXT_STATE_H_
...@@ -7,18 +7,24 @@ ...@@ -7,18 +7,24 @@
#include <limits> #include <limits>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/raster_cmd_format.h" #include "gpu/command_buffer/common/raster_cmd_format.h"
#include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/query_manager.h"
#include "gpu/command_buffer/service/raster_decoder_context_state.h"
#include "gpu/command_buffer/service/raster_decoder_unittest_base.h" #include "gpu/command_buffer/service/raster_decoder_unittest_base.h"
#include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/test_helper.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_image_stub.h"
#include "ui/gl/gl_mock.h" #include "ui/gl/gl_mock.h"
#include "ui/gl/gl_surface_stub.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/gl/test/gl_surface_test_support.h"
using ::testing::_; using ::testing::_;
using ::testing::Return; using ::testing::Return;
...@@ -523,5 +529,123 @@ TEST_P(RasterDecoderTest, YieldAfterEndRasterCHROMIUM) { ...@@ -523,5 +529,123 @@ TEST_P(RasterDecoderTest, YieldAfterEndRasterCHROMIUM) {
EXPECT_EQ(error::kDeferLaterCommands, ExecuteCmd(end_raster_cmd)); EXPECT_EQ(error::kDeferLaterCommands, ExecuteCmd(end_raster_cmd));
} }
class RasterDecoderOOPTest : public testing::Test, DecoderClient {
public:
RasterDecoderOOPTest() : shader_translator_cache_(gpu_preferences_) {}
void SetUp() override {
gl::GLSurfaceTestSupport::InitializeOneOff();
gpu::GpuDriverBugWorkarounds workarounds;
scoped_refptr<gl::GLShareGroup> share_group = new gl::GLShareGroup();
scoped_refptr<gl::GLSurface> surface =
gl::init::CreateOffscreenGLSurface(gfx::Size());
scoped_refptr<gl::GLContext> context = gl::init::CreateGLContext(
share_group.get(), surface.get(), gl::GLContextAttribs());
ASSERT_TRUE(context->MakeCurrent(surface.get()));
context_state_ = new raster::RasterDecoderContextState(
std::move(share_group), std::move(surface), std::move(context),
false /* use_virtualized_gl_contexts */);
context_state_->InitializeGrContext(workarounds);
GpuFeatureInfo gpu_feature_info;
gpu_feature_info.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] =
kGpuFeatureStatusEnabled;
scoped_refptr<gles2::FeatureInfo> feature_info =
new gles2::FeatureInfo(workarounds, gpu_feature_info);
group_ = new gles2::ContextGroup(
gpu_preferences_, false, &mailbox_manager_,
nullptr /* memory_tracker */, &shader_translator_cache_,
&framebuffer_completeness_cache_, feature_info,
false /* bind_generates_resource */, &image_manager_,
nullptr /* image_factory */, nullptr /* progress_reporter */,
gpu_feature_info, &discardable_manager_);
}
void TearDown() override {
context_state_ = nullptr;
gl::init::ShutdownGL(false);
}
// DecoderClient implementation.
void OnConsoleMessage(int32_t id, const std::string& message) override {}
void CacheShader(const std::string& key, const std::string& shader) override {
}
void OnFenceSyncRelease(uint64_t release) override {}
bool OnWaitSyncToken(const gpu::SyncToken&) override { return false; }
void OnDescheduleUntilFinished() override {}
void OnRescheduleAfterFinished() override {}
void OnSwapBuffers(uint64_t swap_id, uint32_t flags) override {}
std::unique_ptr<RasterDecoder> CreateDecoder() {
auto decoder = base::WrapUnique(
RasterDecoder::Create(this, &command_buffer_service_, &outputter_,
group_.get(), context_state_));
ContextCreationAttribs attribs;
attribs.enable_oop_rasterization = true;
attribs.enable_raster_interface = true;
CHECK_EQ(
decoder->Initialize(context_state_->surface, context_state_->context,
true, gles2::DisallowedFeatures(), attribs),
ContextResult::kSuccess);
return decoder;
}
template <typename T>
error::Error ExecuteCmd(RasterDecoder* decoder, const T& cmd) {
static_assert(T::kArgFlags == cmd::kFixed,
"T::kArgFlags should equal cmd::kFixed");
int entries_processed = 0;
return decoder->DoCommands(1, (const void*)&cmd,
ComputeNumEntries(sizeof(cmd)),
&entries_processed);
}
protected:
gles2::TraceOutputter outputter_;
FakeCommandBufferServiceBase command_buffer_service_;
scoped_refptr<RasterDecoderContextState> context_state_;
GpuPreferences gpu_preferences_;
gles2::MailboxManagerImpl mailbox_manager_;
gles2::ShaderTranslatorCache shader_translator_cache_;
gles2::FramebufferCompletenessCache framebuffer_completeness_cache_;
gles2::ImageManager image_manager_;
ServiceDiscardableManager discardable_manager_;
scoped_refptr<gles2::ContextGroup> group_;
};
TEST_F(RasterDecoderOOPTest, StateRestoreAcrossDecoders) {
// First decoder receives a skia command requiring context state reset.
auto decoder1 = CreateDecoder();
EXPECT_FALSE(context_state_->need_context_state_reset);
decoder1->SetUpForRasterCHROMIUMForTest();
cmds::EndRasterCHROMIUM end_raster_cmd;
end_raster_cmd.Init();
EXPECT_FALSE(error::IsError(ExecuteCmd(decoder1.get(), end_raster_cmd)));
EXPECT_TRUE(context_state_->need_context_state_reset);
// Another decoder receives a command which does not require consistent state,
// it should be processed without state restoration.
auto decoder2 = CreateDecoder();
decoder2->SetUpForRasterCHROMIUMForTest();
EXPECT_FALSE(error::IsError(ExecuteCmd(decoder2.get(), end_raster_cmd)));
EXPECT_TRUE(context_state_->need_context_state_reset);
// Now process a command which requires consistent state.
cmds::CreateTexture create_tex_cmd;
create_tex_cmd.Init(false, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
viz::ResourceFormat::RGBA_8888, 4);
EXPECT_FALSE(error::IsError(ExecuteCmd(decoder2.get(), create_tex_cmd)));
EXPECT_FALSE(context_state_->need_context_state_reset);
decoder1->Destroy(true);
context_state_->context->MakeCurrent(context_state_->surface.get());
decoder2->Destroy(true);
// Make sure the context is preserved across decoders.
EXPECT_FALSE(context_state_->gr_context->abandoned());
}
} // namespace raster } // namespace raster
} // namespace gpu } // namespace gpu
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/raster_decoder_context_state.h"
#include "gpu/command_buffer/service/service_utils.h" #include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/test_helper.h"
#include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h"
...@@ -264,8 +265,13 @@ void RasterDecoderTestBase::InitDecoder(const InitState& init) { ...@@ -264,8 +265,13 @@ void RasterDecoderTestBase::InitDecoder(const InitState& init) {
SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable()); SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable());
SetupInitStateExpectations(group_->feature_info()->IsES3Capable()); SetupInitStateExpectations(group_->feature_info()->IsES3Capable());
scoped_refptr<raster::RasterDecoderContextState> context_state =
new raster::RasterDecoderContextState(
new gl::GLShareGroup(), surface_, context_,
feature_info->workarounds().use_virtualized_gl_contexts);
decoder_.reset(RasterDecoder::Create(this, command_buffer_service_.get(), decoder_.reset(RasterDecoder::Create(this, command_buffer_service_.get(),
&outputter_, group_.get())); &outputter_, group_.get(),
std::move(context_state)));
decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_); decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_);
decoder_->GetLogger()->set_log_synthesized_gl_errors(false); decoder_->GetLogger()->set_log_synthesized_gl_errors(false);
......
...@@ -37,10 +37,16 @@ bool GetUintFromSwitch(const base::CommandLine* command_line, ...@@ -37,10 +37,16 @@ bool GetUintFromSwitch(const base::CommandLine* command_line,
gl::GLContextAttribs GenerateGLContextAttribs( gl::GLContextAttribs GenerateGLContextAttribs(
const ContextCreationAttribs& attribs_helper, const ContextCreationAttribs& attribs_helper,
const ContextGroup* context_group) { const ContextGroup* context_group) {
DCHECK(context_group != nullptr); return GenerateGLContextAttribs(attribs_helper,
context_group->use_passthrough_cmd_decoder());
}
gl::GLContextAttribs GenerateGLContextAttribs(
const ContextCreationAttribs& attribs_helper,
bool use_passthrough_cmd_decoder) {
gl::GLContextAttribs attribs; gl::GLContextAttribs attribs;
attribs.gpu_preference = attribs_helper.gpu_preference; attribs.gpu_preference = attribs_helper.gpu_preference;
if (context_group->use_passthrough_cmd_decoder()) { if (use_passthrough_cmd_decoder) {
attribs.bind_generates_resource = attribs_helper.bind_generates_resource; attribs.bind_generates_resource = attribs_helper.bind_generates_resource;
attribs.webgl_compatibility_context = attribs.webgl_compatibility_context =
IsWebGLContextType(attribs_helper.context_type); IsWebGLContextType(attribs_helper.context_type);
......
...@@ -20,6 +20,10 @@ GPU_GLES2_EXPORT gl::GLContextAttribs GenerateGLContextAttribs( ...@@ -20,6 +20,10 @@ GPU_GLES2_EXPORT gl::GLContextAttribs GenerateGLContextAttribs(
const ContextCreationAttribs& attribs_helper, const ContextCreationAttribs& attribs_helper,
const ContextGroup* context_group); const ContextGroup* context_group);
GPU_GLES2_EXPORT gl::GLContextAttribs GenerateGLContextAttribs(
const ContextCreationAttribs& attribs_helper,
bool use_passthrough_cmd_decoder);
// Returns true if the passthrough command decoder has been requested // Returns true if the passthrough command decoder has been requested
GPU_GLES2_EXPORT bool UsePassthroughCommandDecoder( GPU_GLES2_EXPORT bool UsePassthroughCommandDecoder(
const base::CommandLine* command_line); const base::CommandLine* command_line);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/raster_decoder.h" #include "gpu/command_buffer/service/raster_decoder.h"
#include "gpu/command_buffer/service/raster_decoder_context_state.h"
#include "gpu/command_buffer/service/service_discardable_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h"
#include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h"
...@@ -354,9 +355,14 @@ class CommandBufferSetup { ...@@ -354,9 +355,14 @@ class CommandBufferSetup {
#if defined(GPU_FUZZER_USE_RASTER_DECODER) #if defined(GPU_FUZZER_USE_RASTER_DECODER)
CHECK(feature_info->feature_flags().chromium_raster_transport); CHECK(feature_info->feature_flags().chromium_raster_transport);
scoped_refptr<raster::RasterDecoderContextState> context_state =
new raster::RasterDecoderContextState(
share_group_, surface_, context_,
config_.workarounds.use_virtualized_gl_contexts);
context_state->InitializeGrContext(config_.workarounds);
decoder_.reset(raster::RasterDecoder::Create( decoder_.reset(raster::RasterDecoder::Create(
command_buffer_.get(), command_buffer_->service(), &outputter_, command_buffer_.get(), command_buffer_->service(), &outputter_,
context_group.get())); context_group.get(), std::move(context_state)));
#else #else
decoder_.reset(gles2::GLES2Decoder::Create( decoder_.reset(gles2::GLES2Decoder::Create(
command_buffer_.get(), command_buffer_->service(), &outputter_, command_buffer_.get(), command_buffer_->service(), &outputter_,
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/query_manager.h"
#include "gpu/command_buffer/service/raster_decoder.h" #include "gpu/command_buffer/service/raster_decoder.h"
#include "gpu/command_buffer/service/raster_decoder_context_state.h"
#include "gpu/command_buffer/service/service_utils.h" #include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h"
...@@ -64,6 +65,8 @@ ...@@ -64,6 +65,8 @@
#include "ui/gl/gl_image.h" #include "ui/gl/gl_image.h"
#include "ui/gl/gl_image_shared_memory.h" #include "ui/gl/gl_image_shared_memory.h"
#include "ui/gl/gl_share_group.h" #include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/init/create_gr_gl_interface.h"
#include "ui/gl/init/gl_factory.h" #include "ui/gl/init/gl_factory.h"
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -275,11 +278,11 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( ...@@ -275,11 +278,11 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread(
// |context_group_| instead. // |context_group_| instead.
transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr); transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
GpuDriverBugWorkarounds workarounds(
task_executor_->gpu_feature_info().enabled_gpu_driver_bug_workarounds);
if (params.share_command_buffer) { if (params.share_command_buffer) {
context_group_ = params.share_command_buffer->context_group_; context_group_ = params.share_command_buffer->context_group_;
} else { } else {
GpuDriverBugWorkarounds workarounds(
task_executor_->gpu_feature_info().enabled_gpu_driver_bug_workarounds);
auto feature_info = base::MakeRefCounted<gles2::FeatureInfo>( auto feature_info = base::MakeRefCounted<gles2::FeatureInfo>(
workarounds, task_executor_->gpu_feature_info()); workarounds, task_executor_->gpu_feature_info());
...@@ -314,22 +317,6 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( ...@@ -314,22 +317,6 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread(
command_buffer_ = std::make_unique<CommandBufferService>( command_buffer_ = std::make_unique<CommandBufferService>(
this, transfer_buffer_manager_.get()); this, transfer_buffer_manager_.get());
bool supports_oop_rasterization =
task_executor_->gpu_feature_info()
.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] ==
kGpuFeatureStatusEnabled;
if (supports_oop_rasterization && params.attribs.enable_oop_rasterization &&
params.attribs.enable_raster_interface &&
!params.attribs.enable_gles2_interface) {
decoder_.reset(raster::RasterDecoder::Create(this, command_buffer_.get(),
task_executor_->outputter(),
context_group_.get()));
} else {
decoder_.reset(gles2::GLES2Decoder::Create(this, command_buffer_.get(),
task_executor_->outputter(),
context_group_.get()));
}
if (!surface_) { if (!surface_) {
if (params.is_offscreen) { if (params.is_offscreen) {
// TODO(crbug.com/832243): GLES2CommandBufferStub has additional logic for // TODO(crbug.com/832243): GLES2CommandBufferStub has additional logic for
...@@ -396,31 +383,64 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( ...@@ -396,31 +383,64 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread(
crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
: "0"); : "0");
if (use_virtualized_gl_context_) { // TODO(khushalsagar): A lot of this initialization code is duplicated in
DCHECK(gl_share_group_); // GpuChannelManager. Pull it into a common util method.
scoped_refptr<gl::GLContext> real_context = scoped_refptr<gl::GLContext> real_context =
gl_share_group_->GetSharedContext(surface_.get()); use_virtualized_gl_context_
if (!real_context.get()) { ? gl_share_group_->GetSharedContext(surface_.get())
real_context = gl::init::CreateGLContext( : nullptr;
gl_share_group_.get(), surface_.get(), if (!real_context) {
GenerateGLContextAttribs(params.attribs, context_group_.get())); real_context = gl::init::CreateGLContext(
if (!real_context) { gl_share_group_.get(), surface_.get(),
// TODO(piman): This might not be fatal, we could recurse into GenerateGLContextAttribs(params.attribs, context_group_.get()));
// CreateGLContext to get more info, tho it should be exceedingly if (!real_context) {
// rare and may not be recoverable anyway. // TODO(piman): This might not be fatal, we could recurse into
DestroyOnGpuThread(); // CreateGLContext to get more info, tho it should be exceedingly
LOG(ERROR) << "ContextResult::kFatalFailure: " // rare and may not be recoverable anyway.
"Failed to create shared context for virtualization."; DestroyOnGpuThread();
return gpu::ContextResult::kFatalFailure; LOG(ERROR) << "ContextResult::kFatalFailure: "
} "Failed to create shared context for virtualization.";
// Ensure that context creation did not lose track of the intended share return gpu::ContextResult::kFatalFailure;
// group. }
DCHECK(real_context->share_group() == gl_share_group_.get()); // Ensure that context creation did not lose track of the intended share
// group.
DCHECK(real_context->share_group() == gl_share_group_.get());
task_executor_->gpu_feature_info().ApplyToGLContext(real_context.get());
if (use_virtualized_gl_context_)
gl_share_group_->SetSharedContext(surface_.get(), real_context.get()); gl_share_group_->SetSharedContext(surface_.get(), real_context.get());
}
task_executor_->gpu_feature_info().ApplyToGLContext(real_context.get()); if (!real_context->MakeCurrent(surface_.get())) {
} LOG(ERROR)
<< "ContextResult::kTransientFailure, failed to make context current";
DestroyOnGpuThread();
return ContextResult::kTransientFailure;
}
bool supports_oop_rasterization =
task_executor_->gpu_feature_info()
.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] ==
kGpuFeatureStatusEnabled;
if (supports_oop_rasterization && params.attribs.enable_oop_rasterization &&
params.attribs.enable_raster_interface &&
!params.attribs.enable_gles2_interface) {
scoped_refptr<raster::RasterDecoderContextState> context_state =
new raster::RasterDecoderContextState(gl_share_group_, surface_,
real_context,
use_virtualized_gl_context_);
context_state->InitializeGrContext(workarounds);
decoder_.reset(raster::RasterDecoder::Create(
this, command_buffer_.get(), task_executor_->outputter(),
context_group_.get(), std::move(context_state)));
} else {
decoder_.reset(gles2::GLES2Decoder::Create(this, command_buffer_.get(),
task_executor_->outputter(),
context_group_.get()));
}
if (use_virtualized_gl_context_) {
context_ = base::MakeRefCounted<GLContextVirtual>( context_ = base::MakeRefCounted<GLContextVirtual>(
gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr()); gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr());
if (!context_->Initialize( if (!context_->Initialize(
...@@ -434,29 +454,20 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( ...@@ -434,29 +454,20 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread(
"Failed to initialize virtual GL context."; "Failed to initialize virtual GL context.";
return gpu::ContextResult::kFatalFailure; return gpu::ContextResult::kFatalFailure;
} }
} else {
context_ = gl::init::CreateGLContext( if (!context_->MakeCurrent(surface_.get())) {
gl_share_group_.get(), surface_.get(),
GenerateGLContextAttribs(params.attribs, context_group_.get()));
if (!context_) {
DestroyOnGpuThread(); DestroyOnGpuThread();
LOG(ERROR) << "ContextResult::kFatalFailure: Failed to create context."; // The caller should retry making a context, but this one won't work.
return gpu::ContextResult::kFatalFailure; LOG(ERROR) << "ContextResult::kTransientFailure: "
"Could not make context current.";
return gpu::ContextResult::kTransientFailure;
} }
task_executor_->gpu_feature_info().ApplyToGLContext(context_.get());
}
if (!context_->MakeCurrent(surface_.get())) {
DestroyOnGpuThread();
// The caller should retry making a context, but this one won't work.
LOG(ERROR) << "ContextResult::kTransientFailure: "
"Could not make context current.";
return gpu::ContextResult::kTransientFailure;
}
if (!context_->GetGLStateRestorer()) {
context_->SetGLStateRestorer( context_->SetGLStateRestorer(
new GLStateRestorerImpl(decoder_->AsWeakPtr())); new GLStateRestorerImpl(decoder_->AsWeakPtr()));
} else {
context_ = real_context;
DCHECK(context_->IsCurrent(surface_.get()));
} }
if (!context_group_->has_program_cache() && if (!context_group_->has_program_cache() &&
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "gpu/ipc/service/gpu_memory_manager.h" #include "gpu/ipc/service/gpu_memory_manager.h"
#include "ui/gl/gl_bindings.h" #include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_share_group.h" #include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/init/gl_factory.h" #include "ui/gl/init/gl_factory.h"
namespace gpu { namespace gpu {
...@@ -278,4 +279,112 @@ void GpuChannelManager::HandleMemoryPressure( ...@@ -278,4 +279,112 @@ void GpuChannelManager::HandleMemoryPressure(
discardable_manager_.HandleMemoryPressure(memory_pressure_level); discardable_manager_.HandleMemoryPressure(memory_pressure_level);
} }
scoped_refptr<raster::RasterDecoderContextState>
GpuChannelManager::GetRasterDecoderContextState(
const ContextCreationAttribs& requested_attribs,
ContextResult* result) {
if (raster_decoder_context_state_ &&
!raster_decoder_context_state_->context_lost) {
return raster_decoder_context_state_;
}
ContextCreationAttribs attribs;
attribs.gpu_preference = gl::PreferIntegratedGpu;
attribs.context_type = CONTEXT_TYPE_OPENGLES2;
attribs.bind_generates_resource = false;
if (attribs.gpu_preference != requested_attribs.gpu_preference ||
attribs.context_type != requested_attribs.context_type ||
attribs.bind_generates_resource !=
requested_attribs.bind_generates_resource) {
LOG(ERROR) << "ContextResult::kFatalFailure: Incompatible creation attribs "
"used with RasterDecoder";
*result = ContextResult::kFatalFailure;
}
scoped_refptr<gl::GLSurface> surface = GetDefaultOffscreenSurface();
if (!surface) {
LOG(ERROR) << "Failed to create offscreen surface";
*result = ContextResult::kFatalFailure;
return nullptr;
}
bool use_virtualized_gl_contexts = false;
#if defined(OS_MACOSX)
// Virtualize PreferIntegratedGpu contexts by default on OS X to prevent
// performance regressions when enabling FCM.
// http://crbug.com/180463
if (attribs.gpu_preference == gl::PreferIntegratedGpu)
use_virtualized_gl_contexts = true;
#endif
use_virtualized_gl_contexts |=
gpu_driver_bug_workarounds_.use_virtualized_gl_contexts;
// MailboxManagerSync synchronization correctness currently depends on having
// only a single context. See crbug.com/510243 for details.
use_virtualized_gl_contexts |= mailbox_manager_->UsesSync();
const bool use_passthrough_decoder =
gles2::PassthroughCommandDecoderSupported() &&
gpu_preferences_.use_passthrough_cmd_decoder;
scoped_refptr<gl::GLShareGroup> share_group;
if (use_passthrough_decoder) {
share_group = new gl::GLShareGroup();
} else {
share_group = share_group_;
}
scoped_refptr<gl::GLContext> context =
use_virtualized_gl_contexts ? share_group->GetSharedContext(surface.get())
: nullptr;
if (!context) {
context = gl::init::CreateGLContext(
share_group.get(), surface.get(),
gles2::GenerateGLContextAttribs(attribs, use_passthrough_decoder));
if (!context) {
// TODO(piman): This might not be fatal, we could recurse into
// CreateGLContext to get more info, tho it should be exceedingly
// rare and may not be recoverable anyway.
LOG(ERROR) << "ContextResult::kFatalFailure: "
"Failed to create shared context for virtualization.";
*result = ContextResult::kFatalFailure;
return nullptr;
}
// Ensure that context creation did not lose track of the intended share
// group.
DCHECK(context->share_group() == share_group.get());
gpu_feature_info_.ApplyToGLContext(context.get());
if (use_virtualized_gl_contexts)
share_group->SetSharedContext(surface.get(), context.get());
}
// This should be either:
// (1) a non-virtual GL context, or
// (2) a mock/stub context.
DCHECK(context->GetHandle() ||
gl::GetGLImplementation() == gl::kGLImplementationMockGL ||
gl::GetGLImplementation() == gl::kGLImplementationStubGL);
if (!context->MakeCurrent(surface.get())) {
LOG(ERROR)
<< "ContextResult::kTransientFailure, failed to make context current";
*result = ContextResult::kTransientFailure;
return nullptr;
}
raster_decoder_context_state_ = new raster::RasterDecoderContextState(
std::move(share_group), std::move(surface), std::move(context),
use_virtualized_gl_contexts);
const bool enable_raster_transport =
gpu_feature_info_.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] ==
gpu::kGpuFeatureStatusEnabled;
if (enable_raster_transport) {
raster_decoder_context_state_->InitializeGrContext(
gpu_driver_bug_workarounds_);
}
*result = ContextResult::kSuccess;
return raster_decoder_context_state_;
}
} // namespace gpu } // namespace gpu
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "gpu/command_buffer/common/activity_flags.h" #include "gpu/command_buffer/common/activity_flags.h"
#include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/service/raster_decoder_context_state.h"
#include "gpu/command_buffer/service/service_discardable_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h"
#include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/command_buffer/service/shader_translator_cache.h"
#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/config/gpu_driver_bug_workarounds.h"
...@@ -133,6 +134,10 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager { ...@@ -133,6 +134,10 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager {
SyncPointManager* sync_point_manager() const { return sync_point_manager_; } SyncPointManager* sync_point_manager() const { return sync_point_manager_; }
scoped_refptr<raster::RasterDecoderContextState> GetRasterDecoderContextState(
const ContextCreationAttribs& attribs,
ContextResult* result);
private: private:
void InternalDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id); void InternalDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id);
void InternalDestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id, void InternalDestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id,
...@@ -191,6 +196,19 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager { ...@@ -191,6 +196,19 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager {
base::MemoryPressureListener memory_pressure_listener_; base::MemoryPressureListener memory_pressure_listener_;
// The RasterDecoderContextState is shared across all RasterDecoders. Note
// that this class needs to be ref-counted to conveniently manage the lifetime
// of the shared context in the case of a context loss. While the
// RasterDecoders strictly outlive the GpuChannelManager, in the event of a
// context loss the clients need to re-create the GpuChannel and command
// buffers once notified. In this interim state we can have multiple instances
// of the RasterDecoderContextState, for the lost and recovered clients. In
// order to avoid having the GpuChannelManager keep the lost context state
// alive until all clients have recovered, we use a ref-counted object and
// allow the decoders to manage its lifetime.
scoped_refptr<raster::RasterDecoderContextState>
raster_decoder_context_state_;
// Member variables should appear before the WeakPtrFactory, to ensure // Member variables should appear before the WeakPtrFactory, to ensure
// that any WeakPtrs to Controller are invalidated before its members // that any WeakPtrs to Controller are invalidated before its members
// variable's destructors are executed, rendering them invalid. // variable's destructors are executed, rendering them invalid.
......
...@@ -88,6 +88,12 @@ gpu::ContextResult RasterCommandBufferStub::Initialize( ...@@ -88,6 +88,12 @@ gpu::ContextResult RasterCommandBufferStub::Initialize(
return ContextResult::kFatalFailure; return ContextResult::kFatalFailure;
} }
if (surface_handle_ != kNullSurfaceHandle) {
LOG(ERROR) << "ContextResult::kFatalFailure: "
"RenderInterface clients must render offscreen.";
return gpu::ContextResult::kFatalFailure;
}
scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo( scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo(
manager->gpu_driver_bug_workarounds(), manager->gpu_feature_info()); manager->gpu_driver_bug_workarounds(), manager->gpu_feature_info());
gpu::GpuMemoryBufferFactory* gmb_factory = gpu::GpuMemoryBufferFactory* gmb_factory =
...@@ -102,87 +108,37 @@ gpu::ContextResult RasterCommandBufferStub::Initialize( ...@@ -102,87 +108,37 @@ gpu::ContextResult RasterCommandBufferStub::Initialize(
manager->watchdog() /* progress_reporter */, manager->gpu_feature_info(), manager->watchdog() /* progress_reporter */, manager->gpu_feature_info(),
manager->discardable_manager()); manager->discardable_manager());
#if defined(OS_MACOSX) ContextResult result;
// Virtualize PreferIntegratedGpu contexts by default on OS X to prevent auto raster_decoder_context_state =
// performance regressions when enabling FCM. manager->GetRasterDecoderContextState(init_params.attribs, &result);
// http://crbug.com/180463 if (!raster_decoder_context_state) {
if (init_params.attribs.gpu_preference == gl::PreferIntegratedGpu)
use_virtualized_gl_context_ = true;
#endif
use_virtualized_gl_context_ |=
context_group_->feature_info()->workarounds().use_virtualized_gl_contexts;
// MailboxManagerSync synchronization correctness currently depends on having
// only a single context. See crbug.com/510243 for details.
use_virtualized_gl_context_ |= manager->mailbox_manager()->UsesSync();
if (surface_handle_ != kNullSurfaceHandle) {
LOG(ERROR) << "ContextResult::kFatalFailure: " LOG(ERROR) << "ContextResult::kFatalFailure: "
"RenderInterface clients must render offscreen."; "Failed to create raster decoder state.";
return gpu::ContextResult::kFatalFailure; DCHECK_NE(result, gpu::ContextResult::kSuccess);
return result;
} }
surface_ = manager->GetDefaultOffscreenSurface(); surface_ = raster_decoder_context_state->surface;
if (!surface_) { share_group_ = raster_decoder_context_state->share_group;
LOG(ERROR) << "ContextResult::kFatalFailure: " use_virtualized_gl_context_ =
"Failed to create default offscreen surface."; raster_decoder_context_state->use_virtualized_gl_contexts;
return gpu::ContextResult::kFatalFailure;
}
command_buffer_ = std::make_unique<CommandBufferService>( command_buffer_ = std::make_unique<CommandBufferService>(
this, context_group_->transfer_buffer_manager()); this, context_group_->transfer_buffer_manager());
std::unique_ptr<raster::RasterDecoder> decoder(raster::RasterDecoder::Create( std::unique_ptr<raster::RasterDecoder> decoder(raster::RasterDecoder::Create(
this, command_buffer_.get(), manager->outputter(), context_group_.get())); this, command_buffer_.get(), manager->outputter(), context_group_.get(),
raster_decoder_context_state));
sync_point_client_state_ = sync_point_client_state_ =
channel_->sync_point_manager()->CreateSyncPointClientState( channel_->sync_point_manager()->CreateSyncPointClientState(
CommandBufferNamespace::GPU_IO, command_buffer_id_, sequence_id_); CommandBufferNamespace::GPU_IO, command_buffer_id_, sequence_id_);
if (context_group_->use_passthrough_cmd_decoder()) {
// When using the passthrough command decoder, only share with other
// contexts in the explicitly requested share group
share_group_ = new gl::GLShareGroup();
} else {
// When using the validating command decoder, always use the global share
// group
share_group_ = channel_->share_group();
}
// TODO(sunnyps): Should this use ScopedCrashKey instead? // TODO(sunnyps): Should this use ScopedCrashKey instead?
crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
: "0"); : "0");
scoped_refptr<gl::GLContext> context; scoped_refptr<gl::GLContext> context = raster_decoder_context_state->context;
if (use_virtualized_gl_context_) { if (use_virtualized_gl_context_) {
context = share_group_->GetSharedContext(surface_.get());
if (!context) {
context = gl::init::CreateGLContext(
share_group_.get(), surface_.get(),
GenerateGLContextAttribs(init_params.attribs, context_group_.get()));
if (!context) {
// TODO(piman): This might not be fatal, we could recurse into
// CreateGLContext to get more info, tho it should be exceedingly
// rare and may not be recoverable anyway.
LOG(ERROR) << "ContextResult::kFatalFailure: "
"Failed to create shared context for virtualization.";
return gpu::ContextResult::kFatalFailure;
}
// Ensure that context creation did not lose track of the intended share
// group.
DCHECK(context->share_group() == share_group_.get());
share_group_->SetSharedContext(surface_.get(), context.get());
// This needs to be called against the real shared context, not the
// virtual context created below.
manager->gpu_feature_info().ApplyToGLContext(context.get());
}
// This should be either:
// (1) a non-virtual GL context, or
// (2) a mock/stub context.
DCHECK(context->GetHandle() ||
gl::GetGLImplementation() == gl::kGLImplementationMockGL ||
gl::GetGLImplementation() == gl::kGLImplementationStubGL);
context = base::MakeRefCounted<GLContextVirtual>( context = base::MakeRefCounted<GLContextVirtual>(
share_group_.get(), context.get(), decoder->AsWeakPtr()); share_group_.get(), context.get(), decoder->AsWeakPtr());
if (!context->Initialize(surface_.get(), if (!context->Initialize(surface_.get(),
...@@ -198,19 +154,8 @@ gpu::ContextResult RasterCommandBufferStub::Initialize( ...@@ -198,19 +154,8 @@ gpu::ContextResult RasterCommandBufferStub::Initialize(
"Failed to initialize virtual GL context."; "Failed to initialize virtual GL context.";
return gpu::ContextResult::kFatalFailure; return gpu::ContextResult::kFatalFailure;
} }
} else {
context = gl::init::CreateGLContext(
share_group_.get(), surface_.get(),
GenerateGLContextAttribs(init_params.attribs, context_group_.get()));
if (!context) {
// TODO(piman): This might not be fatal, we could recurse into
// CreateGLContext to get more info, tho it should be exceedingly
// rare and may not be recoverable anyway.
LOG(ERROR) << "ContextResult::kFatalFailure: Failed to create context.";
return gpu::ContextResult::kFatalFailure;
}
manager->gpu_feature_info().ApplyToGLContext(context.get()); context->SetGLStateRestorer(new GLStateRestorerImpl(decoder->AsWeakPtr()));
} }
if (!context->MakeCurrent(surface_.get())) { if (!context->MakeCurrent(surface_.get())) {
...@@ -219,19 +164,15 @@ gpu::ContextResult RasterCommandBufferStub::Initialize( ...@@ -219,19 +164,15 @@ gpu::ContextResult RasterCommandBufferStub::Initialize(
return gpu::ContextResult::kTransientFailure; return gpu::ContextResult::kTransientFailure;
} }
if (!context->GetGLStateRestorer()) {
context->SetGLStateRestorer(new GLStateRestorerImpl(decoder->AsWeakPtr()));
}
if (!context_group_->has_program_cache() && if (!context_group_->has_program_cache() &&
!context_group_->feature_info()->workarounds().disable_program_cache) { !context_group_->feature_info()->workarounds().disable_program_cache) {
context_group_->set_program_cache(manager->program_cache()); context_group_->set_program_cache(manager->program_cache());
} }
// Initialize the decoder with either the view or pbuffer GLContext. // Initialize the decoder with either the view or pbuffer GLContext.
auto result = decoder->Initialize(surface_, context, true /* offscreen */, result = decoder->Initialize(surface_, context, true /* offscreen */,
gpu::gles2::DisallowedFeatures(), gpu::gles2::DisallowedFeatures(),
init_params.attribs); init_params.attribs);
if (result != gpu::ContextResult::kSuccess) { if (result != gpu::ContextResult::kSuccess) {
DLOG(ERROR) << "Failed to initialize decoder."; DLOG(ERROR) << "Failed to initialize decoder.";
return result; return result;
......
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