• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef TESTING_LIBFUZZER_FUZZERS_COMMAND_BUFFER_LPM_FUZZER_CMD_BUF_LPM_FUZZ_H_
6 #define TESTING_LIBFUZZER_FUZZERS_COMMAND_BUFFER_LPM_FUZZER_CMD_BUF_LPM_FUZZ_H_
7 
8 #include <dawn/native/DawnNative.h>
9 #include <dawn/webgpu_cpp.h>
10 #include <dawn/wire/WireServer.h>
11 
12 #include "base/functional/bind.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/synchronization/lock.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/test_simple_task_runner.h"
17 #include "base/test/test_suite.h"
18 #include "build/build_config.h"
19 #include "components/viz/test/test_gpu_service_holder.h"
20 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
21 #include "gpu/command_buffer/client/webgpu_cmd_helper.h"
22 #include "gpu/command_buffer/client/webgpu_implementation.h"
23 #include "gpu/command_buffer/service/webgpu_decoder.h"
24 #include "gpu/config/gpu_preferences.h"
25 #include "gpu/ipc/webgpu_in_process_context.h"
26 #include "ui/gl/buildflags.h"
27 
28 #include "testing/libfuzzer/fuzzers/command_buffer_lpm_fuzzer/cmd_buf_lpm_fuzz.pb.h"
29 #include "testing/libfuzzer/fuzzers/command_buffer_lpm_fuzzer/webgpu_support.h"
30 
31 namespace gpu::cmdbuf::fuzzing {
32 
33 const uint32_t kCommandBufferSize = 16384;
34 const uint32_t kTransferBufferSize = 16384;
35 const uint32_t kSmallTransferBufferSize = 16;
36 const uint32_t kTinyTransferBufferSize = 3;
37 
38 const base::TimeDelta kTinyTimeout = base::Milliseconds(100);
39 
40 struct Config {};
41 
42 class CmdBufFuzz : public base::TestSuite {
43  public:
44   CmdBufFuzz();
45   ~CmdBufFuzz() override;
46   void CommandLineInit();
47   void GfxInit();
48 
49   void RuntimeInit();
50   bool Reset();
51 
52   // CommandBuffer ops
53   void RunCommandBuffer(cmdbuf::fuzzing::CmdBufSession);
54   bool CmdBufReset();
55   gpu::SyncToken SyncTokenFromProto(cmdbuf::fuzzing::SyncToken token_proto);
56   void SignalSyncTokenCallback();
57 
58   // WebGPU ops
59   void WebGPURequestAdapter();
60   void WebGPURequestDevice();
61   void WebGPUDestroyDevice();
62   void WebGPUCreateBuffer();
63   void WebGPUDestroyBuffer();
64   void WebGPUReset();
65 
webgpu()66   inline gpu::webgpu::WebGPUImplementation* webgpu() {
67     return webgpu_context_->GetImplementation();
68   }
69 
GetDecoder()70   webgpu::WebGPUDecoder* GetDecoder() const {
71     return webgpu_context_->GetCommandBufferForTest()
72         ->GetWebGPUDecoderForTest();
73   }
74 
RunPendingTasks()75   void RunPendingTasks() {
76     webgpu_context_->GetTaskRunner()->RunPendingTasks();
77     gpu_service_holder_->ScheduleGpuMainTask(base::BindOnce(
78         [](webgpu::WebGPUDecoder* decoder) {
79           if (decoder->HasPollingWork()) {
80             LOG(INFO) << "GPU has waiting work";
81             decoder->PerformPollingWork();
82           }
83         },
84         GetDecoder()));
85   }
86 
PollUntilIdle()87   void PollUntilIdle() {
88     webgpu()->FlushCommands();
89     base::WaitableEvent wait;
90     gpu_service_holder_->ScheduleGpuMainTask(base::BindOnce(
91         [](viz::TestGpuServiceHolder* service, base::WaitableEvent* wait,
92            webgpu::WebGPUDecoder* decoder) {
93           service->gpu_main_thread_task_runner()->RunsTasksInCurrentSequence();
94           while (decoder->HasPollingWork()) {
95             base::PlatformThread::Sleep(kTinyTimeout);
96             decoder->PerformPollingWork();
97           }
98           wait->Signal();
99         },
100         gpu_service_holder_.get(), &wait, GetDecoder()));
101     wait.Wait();
102     webgpu_context_->GetTaskRunner()->RunPendingTasks();
103   }
104 
PostTaskToGpuThread(base::OnceClosure callback)105   void PostTaskToGpuThread(base::OnceClosure callback) {
106     gpu_service_holder_->ScheduleGpuMainTask(std::move(callback));
107   }
108 
WaitForCompletion(wgpu::Device device)109   void WaitForCompletion(wgpu::Device device) {
110     // Wait for any work submitted to the queue to be finished. The guarantees
111     // of Dawn are that all previous operations will have been completed and
112     // more importantly the callbacks will have been called.
113     wgpu::Queue queue = device.GetQueue();
114     bool done = false;
115     queue.OnSubmittedWorkDone(
116         0u,
117         [](WGPUQueueWorkDoneStatus, void* userdata) {
118           *static_cast<bool*>(userdata) = true;
119         },
120         &done);
121 
122     while (!done) {
123       device.Tick();
124       webgpu()->FlushCommands();
125       RunPendingTasks();
126       base::PlatformThread::Sleep(kTinyTimeout);
127     }
128   }
129 
130  private:
131   GpuPreferences gpu_preferences_;
132   std::unique_ptr<viz::TestGpuServiceHolder> gpu_service_holder_;
133   std::unique_ptr<WebGPUInProcessContext> webgpu_context_;
134   raw_ptr<gl::GLDisplay> gl_display_;
135   scoped_refptr<gl::GLSurface> surface_;
136   // std::unique_ptr<CommandBufferDirect> command_buffer_;
137   raw_ptr<InProcessCommandBuffer> command_buffer_ = nullptr;
138   std::unique_ptr<CommandBufferService> command_buffer_service_;
139   raw_ptr<CommandBufferHelper> cmd_helper_ = nullptr;
140   std::unique_ptr<webgpu::WebGPUCmdHelper> webgpu_cmd_helper_ = nullptr;
141   // std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_proxy_impl_;
142   //  scoped_refptr<viz::ContextProviderCommandBuffer> provider_;
143   std::unique_ptr<wgpu::Instance> webgpu_instance_;
144   raw_ptr<webgpu::WebGPUDecoder> decoder_;
145   std::unique_ptr<wgpu::Adapter> webgpu_adapter_;
146   std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
147   raw_ptr<gpu::webgpu::WebGPUImplementation> webgpu_impl_;
148   std::unique_ptr<dawn::wire::WireServer> wire_server_;
149   scoped_refptr<webgpu::APIChannel> wire_channel_;
150   std::unique_ptr<dawn::native::Instance> dawn_instance_;
151   std::unique_ptr<DawnProcTable> dawn_procs_;
152   std::unique_ptr<dawn::wire::WireServerDescriptor> wire_descriptor_;
153   scoped_refptr<Buffer> buffer_;
154   int32_t command_buffer_id_ = -1;
155   std::unique_ptr<SharedMemoryLimits> shared_memory_limits_;
156   raw_ptr<CommandBufferTaskExecutor> task_executor_;
157   // scoped_refptr<SharedContextState> shared_context_state_;
158   raw_ptr<webgpu::DawnWireServices> dawn_wire_services_;
159   raw_ptr<webgpu::DawnClientSerializer> dawn_wire_serializer_;
160   wgpu::Device webgpu_device_ = {};
161   std::vector<wgpu::Buffer> wgpu_buffers_ = {};
162 
163   // Actions
164   int action_index_ = 0;
165   base::Lock cmd_buf_lock_;
166 
167   // TODO(bookholt): enable to support GL fuzzing
168   // gpu::gles2::GLES2Interface* gl_interface_;
169   // TODO(bookholt): this looks useful
170   // raw_ptr<gpu::ContextSupport, DanglingUntriaged> context_support_;
171   // TODO(bookohlt)
172   // gpu::GpuChannelEstablishFactory* factory_;
173   // TODO(bookholt)
174   // scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_;
175 };
176 }  // namespace gpu::cmdbuf::fuzzing
177 
178 #endif  // TESTING_LIBFUZZER_FUZZERS_COMMAND_BUFFER_LPM_FUZZER_CMD_BUF_LPM_FUZZ_H_
179