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 [](WGPUQueueWorkDoneStatus, void* userdata) { 117 *static_cast<bool*>(userdata) = true; 118 }, 119 &done); 120 121 while (!done) { 122 device.Tick(); 123 webgpu()->FlushCommands(); 124 RunPendingTasks(); 125 base::PlatformThread::Sleep(kTinyTimeout); 126 } 127 } 128 129 private: 130 GpuPreferences gpu_preferences_; 131 std::unique_ptr<viz::TestGpuServiceHolder> gpu_service_holder_; 132 std::unique_ptr<WebGPUInProcessContext> webgpu_context_; 133 raw_ptr<gl::GLDisplay> gl_display_; 134 scoped_refptr<gl::GLSurface> surface_; 135 // std::unique_ptr<CommandBufferDirect> command_buffer_; 136 raw_ptr<InProcessCommandBuffer> command_buffer_ = nullptr; 137 std::unique_ptr<CommandBufferService> command_buffer_service_; 138 raw_ptr<CommandBufferHelper> cmd_helper_ = nullptr; 139 std::unique_ptr<webgpu::WebGPUCmdHelper> webgpu_cmd_helper_ = nullptr; 140 // std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_proxy_impl_; 141 // scoped_refptr<viz::ContextProviderCommandBuffer> provider_; 142 std::unique_ptr<wgpu::Instance> webgpu_instance_; 143 raw_ptr<webgpu::WebGPUDecoder> decoder_; 144 std::unique_ptr<wgpu::Adapter> webgpu_adapter_; 145 std::unique_ptr<gpu::TransferBuffer> transfer_buffer_; 146 raw_ptr<gpu::webgpu::WebGPUImplementation> webgpu_impl_; 147 std::unique_ptr<dawn::wire::WireServer> wire_server_; 148 scoped_refptr<webgpu::APIChannel> wire_channel_; 149 std::unique_ptr<dawn::native::Instance> dawn_instance_; 150 std::unique_ptr<DawnProcTable> dawn_procs_; 151 std::unique_ptr<dawn::wire::WireServerDescriptor> wire_descriptor_; 152 scoped_refptr<Buffer> buffer_; 153 int32_t command_buffer_id_ = -1; 154 std::unique_ptr<SharedMemoryLimits> shared_memory_limits_; 155 raw_ptr<CommandBufferTaskExecutor> task_executor_; 156 // scoped_refptr<SharedContextState> shared_context_state_; 157 raw_ptr<webgpu::DawnWireServices> dawn_wire_services_; 158 raw_ptr<webgpu::DawnClientSerializer> dawn_wire_serializer_; 159 wgpu::Device webgpu_device_ = {}; 160 std::vector<wgpu::Buffer> wgpu_buffers_ = {}; 161 162 // Actions 163 int action_index_ = 0; 164 base::Lock cmd_buf_lock_; 165 166 // TODO(bookholt): enable to support GL fuzzing 167 // gpu::gles2::GLES2Interface* gl_interface_; 168 // TODO(bookholt): this looks useful 169 // raw_ptr<gpu::ContextSupport, DanglingUntriaged> context_support_; 170 // TODO(bookohlt) 171 // gpu::GpuChannelEstablishFactory* factory_; 172 // TODO(bookholt) 173 // scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_; 174 }; 175 } // namespace gpu::cmdbuf::fuzzing 176 177 #endif // TESTING_LIBFUZZER_FUZZERS_COMMAND_BUFFER_LPM_FUZZER_CMD_BUF_LPM_FUZZ_H_ 178