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