910e62b5创建于 1月15日历史提交
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GPU_IPC_IN_PROCESS_COMMAND_BUFFER_H_
#define GPU_IPC_IN_PROCESS_COMMAND_BUFFER_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "gpu/command_buffer/client/gpu_control.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/context_result.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/command_buffer_task_executor.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/decoder_client.h"
#include "gpu/command_buffer/service/decoder_context.h"
#include "gpu/command_buffer/service/display_compositor_memory_and_task_controller_on_gpu.h"
#include "gpu/command_buffer/service/gpu_task_scheduler_helper.h"
#include "gpu/command_buffer/service/gr_cache_controller.h"
#include "gpu/command_buffer/service/program_cache.h"
#include "gpu/command_buffer/service/service_transfer_cache.h"
#include "gpu/command_buffer/service/shared_image_interface_in_process.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/common/gpu_channel.mojom.h"
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/ipc/gl_in_process_context_export.h"
#include "gpu/ipc/service/context_url.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gpu_preference.h"

namespace gl {
class GLContext;
class GLShareGroup;
}

namespace gfx {
struct GpuFenceHandle;
}

namespace gpu {
class SharedContextState;
class GpuProcessShmCount;
class GpuTaskSchedulerHelper;
class FenceSyncReleaseDelegate;
class SharedImageInterface;

namespace webgpu {
class WebGPUDecoder;
}

namespace raster {
class GrShaderCache;
}

// This class provides a thread-safe interface to the global GPU service (for
// example GPU thread) when being run in single process mode.
// However, the behavior for accessing one context (i.e. one instance of this
// class) from different client threads is undefined. See
// ui::InProcessContextProvider for an example of how to define multi-threading
// semantics.
class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer
    : public CommandBuffer,
      public GpuControl,
      public CommandBufferServiceClient,
      public DecoderClient {
 public:
  InProcessCommandBuffer(CommandBufferTaskExecutor* task_executor,
                         const GURL& active_url);

  InProcessCommandBuffer(const InProcessCommandBuffer&) = delete;
  InProcessCommandBuffer& operator=(const InProcessCommandBuffer&) = delete;

  ~InProcessCommandBuffer() override;

  gpu::ContextResult Initialize(
      mojom::ContextCreationAttribsPtr attribs,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
      gpu::raster::GrShaderCache* gr_shader_cache,
      GpuProcessShmCount* use_shader_cache_shm_count);

  // CommandBuffer implementation (called on client thread):
  State GetLastState() override;
  void Flush(int32_t put_offset) override;
  void OrderingBarrier(int32_t put_offset) override;
  State WaitForTokenInRange(int32_t start, int32_t end) override;
  State WaitForGetOffsetInRange(uint32_t set_get_buffer_count,
                                int32_t start,
                                int32_t end) override;
  void SetGetBuffer(int32_t shm_id) override;
  scoped_refptr<Buffer> CreateTransferBuffer(
      uint32_t size,
      int32_t* id,
      uint32_t alignment = 0,
      TransferBufferAllocationOption option =
          TransferBufferAllocationOption::kLoseContextOnOOM) override;
  void DestroyTransferBuffer(int32_t id) override;
  void ForceLostContext(error::ContextLostReason reason) override;

  // GpuControl implementation (called on client thread):
  void SetGpuControlClient(GpuControlClient*) override;
  // GetCapabilities() can be called on any thread.
  const Capabilities& GetCapabilities() const override;
  const GLCapabilities& GetGLCapabilities() const override;
  void SignalQuery(uint32_t query_id, base::OnceClosure callback) override;
  void CancelAllQueries() override;
  void CreateGpuFence(uint32_t gpu_fence_id, ClientGpuFence source) override;
  void GetGpuFence(uint32_t gpu_fence_id,
                   base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)>
                       callback) override;
  void SetLock(base::Lock*) override;
  void EnsureWorkVisible() override;
  CommandBufferNamespace GetNamespaceID() const override;
  CommandBufferId GetCommandBufferID() const override;
  void FlushPendingWork() override;
  uint64_t GenerateFenceSyncRelease() override;
  bool IsFenceSyncReleased(uint64_t release) override;
  void SignalSyncToken(const SyncToken& sync_token,
                       base::OnceClosure callback) override;
  void WaitSyncToken(const SyncToken& sync_token) override;
  bool CanWaitUnverifiedSyncToken(const SyncToken& sync_token) override;

  // CommandBufferServiceClient implementation (called on gpu thread):
  CommandBatchProcessedResult OnCommandBatchProcessed() override;
  void OnParseError() override;

  // DecoderClient implementation (called on gpu thread):
  void OnConsoleMessage(int32_t id, const std::string& message) override;
  void CacheBlob(gpu::GpuDiskCacheType type,
                 const std::string& key,
                 const std::string& shader) override;
  void OnFenceSyncRelease(uint64_t release) override;
  void OnDescheduleUntilFinished() override;
  void OnRescheduleAfterFinished() override;
  void ScheduleGrContextCleanup() override;
  void HandleReturnData(base::span<const uint8_t> data) override;
  bool ShouldYield() override;

  const gles2::FeatureInfo* GetFeatureInfo() const;

  // Upstream this function to GpuControl if needs arise. Can be called on any
  // thread.
  const GpuFeatureInfo& GetGpuFeatureInfo() const;

  gpu::ServiceTransferCache* GetTransferCacheForTest() const;
  int GetRasterDecoderIdForTest() const;
  webgpu::WebGPUDecoder* GetWebGPUDecoderForTest() const;

  CommandBufferTaskExecutor* service_for_testing() const {
    return task_executor_;
  }

  gpu::SharedImageInterface* GetSharedImageInterface() const;

 private:
  struct InitializeOnGpuThreadParams {
    mojom::ContextCreationAttribsPtr attribs;
    raw_ptr<Capabilities> capabilities;       // Output.
    raw_ptr<GLCapabilities> gl_capabilities;  // Output.
    raw_ptr<gpu::raster::GrShaderCache> gr_shader_cache;
    raw_ptr<GpuProcessShmCount> use_shader_cache_shm_count;

    InitializeOnGpuThreadParams(mojom::ContextCreationAttribsPtr attribs,
                                Capabilities* capabilities,
                                GLCapabilities* gl_capabilities,
                                gpu::raster::GrShaderCache* gr_shader_cache,
                                GpuProcessShmCount* use_shader_cache_shm_count);
    ~InitializeOnGpuThreadParams();

    InitializeOnGpuThreadParams(InitializeOnGpuThreadParams&& other);
    InitializeOnGpuThreadParams& operator=(InitializeOnGpuThreadParams&& other);
  };

  // Initialize() and Destroy() are called on the client thread, but post tasks
  // to the gpu thread to perform the actual initialization or destruction.
  gpu::ContextResult InitializeOnGpuThread(
      const InitializeOnGpuThreadParams& params);
  void Destroy();
  bool DestroyOnGpuThread();

  // Flush up to put_offset. If execution is deferred either by yielding, or due
  // to a sync token wait, HasUnprocessedCommandsOnGpuThread() returns true.
  void FlushOnGpuThread(int32_t put_offset,
                        FenceSyncReleaseDelegate* release_delegate);
  bool HasUnprocessedCommandsOnGpuThread();
  void UpdateLastStateOnGpuThread();

  void ScheduleDelayedWorkOnGpuThread();

  bool MakeCurrent();

  void CreateCacheUse(
      std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);

  // Client callbacks are posted back to |origin_task_runner_|, or run
  // synchronously if there's no task runner or message loop.
  void PostOrRunClientCallback(base::OnceClosure callback);
  base::OnceClosure WrapClientCallback(base::OnceClosure callback);

  void RunTaskCallbackOnGpuThread(TaskCallback task,
                                  FenceSyncReleaseDelegate* release_delegate);
  void RunTaskClosureOnGpuThread(base::OnceClosure task);

  void ScheduleGpuTask(
      TaskCallback task,
      std::vector<SyncToken> sync_token_fences = std::vector<SyncToken>(),
      const SyncToken& release = SyncToken());
  void ScheduleGpuTask(
      base::OnceClosure task,
      std::vector<SyncToken> sync_token_fences = std::vector<SyncToken>(),
      const SyncToken& release = SyncToken());
  void ContinueGpuTask(TaskCallback task);

  void SignalQueryOnGpuThread(unsigned query_id, base::OnceClosure callback);
  void CancelAllQueriesOnGpuThread();

  void RegisterTransferBufferOnGpuThread(int32_t id,
                                         scoped_refptr<Buffer> buffer);
  void DestroyTransferBufferOnGpuThread(int32_t id);
  void ForceLostContextOnGpuThread(error::ContextLostReason reason);

  void SetGetBufferOnGpuThread(int32_t shm_id, base::WaitableEvent* completion);

  void CreateGpuFenceOnGpuThread(uint32_t gpu_fence_id,
                                 gfx::GpuFenceHandle handle);
  void GetGpuFenceOnGpuThread(
      uint32_t gpu_fence_id,
      base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback);

  // Sets |active_url_| as the active GPU process URL. Should be called on GPU
  // thread only.
  void UpdateActiveUrl();

  // Callbacks on the gpu thread.
  void PerformDelayedWorkOnGpuThread();

  // Callback implementations on the client thread.
  void OnContextLost();

  void HandleReturnDataOnOriginThread(std::vector<uint8_t> data);

  const CommandBufferId command_buffer_id_;
  const ContextUrl active_url_;

  // Members accessed on the gpu thread (possibly with the exception of
  // creation):
  bool use_virtualized_gl_context_ = false;
  raw_ptr<raster::GrShaderCache> gr_shader_cache_ = nullptr;
  scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
  std::unique_ptr<CommandBufferService> command_buffer_;
  std::unique_ptr<DecoderContext> decoder_;
  scoped_refptr<gl::GLContext> context_;
  ScopedSyncPointClientState sync_point_client_state_;
  // Caching the `release_delegate` argument of Flush() during the call.
  raw_ptr<FenceSyncReleaseDelegate> release_delegate_ = nullptr;

  // Used to throttle PerformDelayedWorkOnGpuThread.
  bool delayed_work_pending_ = false;
  // Sequence checker for tasks that run on the gpu "thread".
  SEQUENCE_CHECKER(gpu_sequence_checker_);

  // Members accessed on the client thread:
  raw_ptr<GpuControlClient> gpu_control_client_ = nullptr;
#if DCHECK_IS_ON()
  bool context_lost_ = false;
#endif
  State last_state_;
  base::Lock last_state_lock_;
  int32_t last_put_offset_ = -1;
  Capabilities capabilities_;
  GLCapabilities gl_capabilities_;
  uint64_t next_fence_sync_release_ = 1;
  std::vector<SyncToken> next_flush_sync_token_fences_;
  // Sequence checker for client sequence used for initialization, destruction,
  // callbacks, such as context loss, and methods which provide such callbacks,
  // such as SignalSyncToken.
  SEQUENCE_CHECKER(client_sequence_checker_);

  // Accessed on both threads:
  base::WaitableEvent flush_event_;
  const raw_ptr<CommandBufferTaskExecutor> task_executor_;

  // If no SingleTaskSequence is passed in, create our own.
  std::unique_ptr<GpuTaskSchedulerHelper> task_scheduler_holder_;

  // Pointer to the SingleTaskSequence that actually does the scheduling.
  raw_ptr<SingleTaskSequence> task_sequence_;
  scoped_refptr<SharedImageInterfaceInProcess> shared_image_interface_;

  // The group of contexts that share namespaces with this context.
  scoped_refptr<gles2::ContextGroup> context_group_;

  scoped_refptr<gl::GLShareGroup> gl_share_group_;
  base::WaitableEvent fence_sync_wait_event_;

  scoped_refptr<SharedContextState> context_state_;

  base::WeakPtr<InProcessCommandBuffer> client_thread_weak_ptr_;

  // Don't use |client_thread_weak_ptr_factory_| on GPU thread.  Use the cached
  // |client_thread_weak_ptr_| instead.
  base::WeakPtrFactory<InProcessCommandBuffer> client_thread_weak_ptr_factory_{
      this};
  base::WeakPtrFactory<InProcessCommandBuffer> gpu_thread_weak_ptr_factory_{
      this};
};

}  // namespace gpu

#endif  // GPU_IPC_IN_PROCESS_COMMAND_BUFFER_H_