#ifndef GPU_IPC_SERVICE_GPU_CHANNEL_MANAGER_H_
#define GPU_IPC_SERVICE_GPU_CHANNEL_MANAGER_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process_handle.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/context_result.h"
#include "gpu/command_buffer/common/shm_count.h"
#include "gpu/command_buffer/service/framebuffer_completeness_cache.h"
#include "gpu/command_buffer/service/gr_cache_controller.h"
#include "gpu/command_buffer/service/gr_shader_cache.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/common/gpu_disk_cache_type.h"
#include "gpu/ipc/common/gpu_peak_memory.h"
#include "gpu/ipc/service/gpu_ipc_service_export.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/gl/gl_surface.h"
namespace base::trace_event {
class TracedValue;
}
namespace gfx {
struct GpuExtraInfo;
}
namespace gl {
class GLShareGroup;
}
namespace gpu {
class DawnContextProvider;
class ImageDecodeAcceleratorWorker;
struct GpuPreferences;
class GpuChannel;
class GpuChannelManagerDelegate;
class GpuWatchdogThread;
class Scheduler;
class SharedImageManager;
class SyncPointManager;
struct VideoMemoryUsageStats;
namespace gles2 {
class Outputter;
class ProgramCache;
}
namespace webgpu {
class DawnCachingInterfaceFactory;
}
class GPU_IPC_SERVICE_EXPORT GpuChannelManager
: public raster::GrShaderCache::Client,
public base::MemoryPressureListener {
public:
GpuChannelManager(
const GpuPreferences& gpu_preferences,
GpuChannelManagerDelegate* delegate,
GpuWatchdogThread* watchdog,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
Scheduler* scheduler,
SyncPointManager* sync_point_manager,
SharedImageManager* shared_image_manager,
const GpuFeatureInfo& gpu_feature_info,
GpuProcessShmCount* use_shader_cache_shm_count,
scoped_refptr<gl::GLSurface> default_offscreen_surface,
viz::VulkanContextProvider* vulkan_context_provider = nullptr,
viz::MetalContextProvider* metal_context_provider = nullptr,
DawnContextProvider* dawn_context_provider = nullptr,
webgpu::DawnCachingInterfaceFactory* dawn_caching_interface_factory =
nullptr,
const SharedContextState::GrContextOptionsProvider*
gr_context_options_provider = nullptr);
GpuChannelManager(const GpuChannelManager&) = delete;
GpuChannelManager& operator=(const GpuChannelManager&) = delete;
~GpuChannelManager() override;
GpuChannelManagerDelegate* delegate() const { return delegate_; }
GpuWatchdogThread* watchdog() const { return watchdog_; }
GpuChannel* EstablishChannel(const base::UnguessableToken& channel_token,
int client_id,
uint64_t client_tracing_id,
bool is_gpu_host,
bool enable_extra_handles_validation,
const gfx::GpuExtraInfo& gpu_extra_info);
void SetChannelClientPid(int client_id, base::ProcessId client_pid);
void SetChannelDiskCacheHandle(int client_id,
const gpu::GpuDiskCacheHandle& handle);
void OnDiskCacheHandleDestoyed(const gpu::GpuDiskCacheHandle& handle);
void PopulateCache(const gpu::GpuDiskCacheHandle& handle,
const std::string& key,
const std::string& program);
#if BUILDFLAG(IS_ANDROID)
void WakeUpGpu();
#endif
void DestroyAllChannels();
void RemoveChannel(int client_id);
void OnContextLost(int context_lost_count,
bool synthetic_loss,
error::ContextLostReason context_lost_reason);
const GpuPreferences& gpu_preferences() const { return gpu_preferences_; }
const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds() const {
return gpu_driver_bug_workarounds_;
}
const GpuFeatureInfo& gpu_feature_info() const { return gpu_feature_info_; }
gles2::Outputter* outputter();
gles2::ProgramCache* program_cache();
gles2::ShaderTranslatorCache* shader_translator_cache() {
return &shader_translator_cache_;
}
gles2::FramebufferCompletenessCache* framebuffer_completeness_cache() {
return &framebuffer_completeness_cache_;
}
GpuChannel* LookupChannel(int32_t client_id) const;
gl::GLSurface* default_offscreen_surface() const {
return default_offscreen_surface_.get();
}
MemoryTracker::Observer* peak_memory_monitor() {
return peak_memory_monitor_.get();
}
GpuProcessShmCount* use_shader_cache_shm_count() {
return use_shader_cache_shm_count_;
}
#if BUILDFLAG(IS_ANDROID)
void DidAccessGpu();
void OnBackgroundCleanup();
#endif
void OnApplicationBackgrounded();
void OnApplicationForegounded();
bool application_backgrounded() const { return application_backgrounded_; }
void PerformImmediateCleanup();
gl::GLShareGroup* share_group() const { return share_group_.get(); }
SyncPointManager* sync_point_manager() const { return sync_point_manager_; }
SharedImageManager* shared_image_manager() const {
return shared_image_manager_;
}
Scheduler* scheduler() const { return scheduler_; }
bool use_passthrough_cmd_decoder() const {
return gpu_preferences_.use_passthrough_cmd_decoder;
}
void GetVideoMemoryUsageStats(
VideoMemoryUsageStats* video_memory_usage_stats) const;
void StartPeakMemoryMonitor(uint32_t sequence_num);
base::flat_map<GpuPeakMemoryAllocationSource, uint64_t> GetPeakMemoryUsage(
uint32_t sequence_num,
uint64_t* out_peak_memory);
scoped_refptr<SharedContextState> GetSharedContextState(
ContextResult* result);
void ScheduleGrContextCleanup();
raster::GrShaderCache* gr_shader_cache() {
return gr_shader_cache_ ? &*gr_shader_cache_ : nullptr;
}
webgpu::DawnCachingInterfaceFactory* dawn_caching_interface_factory() {
return dawn_caching_interface_factory_.get();
}
void StoreShader(const std::string& key, const std::string& shader) override;
void SetImageDecodeAcceleratorWorkerForTesting(
ImageDecodeAcceleratorWorker* worker);
void LoseAllContexts();
SharedContextState::ContextLostCallback GetContextLostCallback();
private:
friend class GpuChannelManagerTest;
class GPU_IPC_SERVICE_EXPORT GpuPeakMemoryMonitor
: public MemoryTracker::Observer {
public:
GpuPeakMemoryMonitor();
GpuPeakMemoryMonitor(const GpuPeakMemoryMonitor&) = delete;
GpuPeakMemoryMonitor& operator=(const GpuPeakMemoryMonitor&) = delete;
base::flat_map<GpuPeakMemoryAllocationSource, uint64_t> GetPeakMemoryUsage(
uint32_t sequence_num,
uint64_t* out_peak_memory);
void StartGpuMemoryTracking(uint32_t sequence_num);
void StopGpuMemoryTracking(uint32_t sequence_num);
protected:
~GpuPeakMemoryMonitor() override;
private:
struct SequenceTracker {
public:
SequenceTracker(uint64_t current_memory,
base::flat_map<GpuPeakMemoryAllocationSource, uint64_t>
current_memory_per_source);
SequenceTracker(const SequenceTracker&);
~SequenceTracker();
uint64_t initial_memory_ = 0u;
uint64_t total_memory_ = 0u;
base::flat_map<GpuPeakMemoryAllocationSource, uint64_t>
initial_memory_per_source_;
base::flat_map<GpuPeakMemoryAllocationSource, uint64_t>
peak_memory_per_source_;
};
std::unique_ptr<base::trace_event::TracedValue> StartTrackingTracedValue()
EXCLUSIVE_LOCKS_REQUIRED(peak_mem_lock_);
std::unique_ptr<base::trace_event::TracedValue> StopTrackingTracedValue(
SequenceTracker& sequence) EXCLUSIVE_LOCKS_REQUIRED(peak_mem_lock_);
void OnMemoryAllocatedChange(
CommandBufferId id,
uint64_t old_size,
uint64_t new_size,
GpuPeakMemoryAllocationSource source =
GpuPeakMemoryAllocationSource::UNKNOWN) override;
base::flat_map<uint32_t, SequenceTracker> sequence_trackers_
GUARDED_BY(peak_mem_lock_);
uint64_t current_memory_ GUARDED_BY(peak_mem_lock_) = 0u;
base::flat_map<GpuPeakMemoryAllocationSource, uint64_t>
current_memory_per_source_ GUARDED_BY(peak_mem_lock_);
mutable base::Lock peak_mem_lock_;
};
#if BUILDFLAG(IS_ANDROID)
void ScheduleWakeUpGpu();
void DoWakeUpGpu();
#endif
void OnMemoryPressure(
base::MemoryPressureLevel memory_pressure_level) override;
base::flat_map<int32_t, std::unique_ptr<GpuChannel>> gpu_channels_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
const GpuPreferences gpu_preferences_;
const GpuDriverBugWorkarounds gpu_driver_bug_workarounds_;
const raw_ptr<GpuChannelManagerDelegate> delegate_;
raw_ptr<GpuWatchdogThread> watchdog_;
scoped_refptr<gl::GLShareGroup> share_group_;
std::unique_ptr<gles2::Outputter> outputter_;
raw_ptr<Scheduler> scheduler_;
const raw_ptr<SyncPointManager> sync_point_manager_;
const raw_ptr<SharedImageManager> shared_image_manager_;
std::unique_ptr<gles2::ProgramCache> program_cache_;
gles2::ShaderTranslatorCache shader_translator_cache_;
gles2::FramebufferCompletenessCache framebuffer_completeness_cache_;
scoped_refptr<gl::GLSurface> default_offscreen_surface_;
GpuFeatureInfo gpu_feature_info_;
#if BUILDFLAG(IS_ANDROID)
base::TimeTicks last_gpu_access_time_;
base::TimeTicks begin_wake_up_time_;
#endif
const raw_ptr<GpuProcessShmCount> use_shader_cache_shm_count_;
base::AsyncMemoryPressureListenerRegistration
memory_pressure_listener_registration_;
std::optional<raster::GrShaderCache> gr_shader_cache_;
scoped_refptr<SharedContextState> shared_context_state_;
raw_ptr<webgpu::DawnCachingInterfaceFactory> dawn_caching_interface_factory_;
raw_ptr<viz::VulkanContextProvider> vulkan_context_provider_ = nullptr;
raw_ptr<viz::MetalContextProvider> metal_context_provider_ = nullptr;
raw_ptr<DawnContextProvider> dawn_context_provider_ = nullptr;
scoped_refptr<GpuPeakMemoryMonitor> peak_memory_monitor_;
raw_ptr<const SharedContextState::GrContextOptionsProvider>
gr_context_options_provider_ = nullptr;
const base::TimeTicks creation_time_ = base::TimeTicks::Now();
base::TimeDelta context_lost_time_;
int context_lost_count_ = 0;
bool application_backgrounded_ = false;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<GpuChannelManager> weak_factory_{this};
};
}
#endif