chromium/testing/libfuzzer/fuzzers/command_buffer_lpm_fuzzer/webgpu_support.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "testing/libfuzzer/fuzzers/command_buffer_lpm_fuzzer/webgpu_support.h"

#include <dawn/webgpu_cpp_print.h>

#include "testing/libfuzzer/fuzzers/command_buffer_lpm_fuzzer/cmd_buf_lpm_fuzz.h"

namespace gpu::cmdbuf::fuzzing {

DawnWireSerializerFuzzer::DawnWireSerializerFuzzer() = default;
DawnWireSerializerFuzzer::~DawnWireSerializerFuzzer() = default;

size_t DawnWireSerializerFuzzer::GetMaximumAllocationSize() const {
  // Some fuzzer bots have a 2GB allocation limit. Pick a value reasonably
  // below that.
  return 1024 * 1024 * 1024;
}

void* DawnWireSerializerFuzzer::GetCmdSpace(size_t size) {
  if (size > buf.size()) {
    buf.resize(size);
  }
  return buf.data();
}

bool DawnWireSerializerFuzzer::Flush() {
  return true;
}

void CmdBufFuzz::WebGPURequestAdapter() {
  DVLOG(3) << "Requesting WebGPU adapter...";
  wgpu::RequestAdapterOptions ra_options = {};
  ra_options.forceFallbackAdapter = false;
  bool done = false;
  webgpu_instance_.RequestAdapter(
      &ra_options, wgpu::CallbackMode::AllowSpontaneous,
      [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter,
          const char* message) {
        CHECK_EQ(status, wgpu::RequestAdapterStatus::Success);
        CHECK_NE(adapter.Get(), nullptr);
        webgpu_adapter_ = std::move(adapter);
        DVLOG(3) << "Adapter acquired";
        done = true;
      });
  webgpu_impl_->FlushCommands();
  while (!done) {
    RunPendingTasks();
    base::PlatformThread::Sleep(kTinyTimeout);
  }
}

void CmdBufFuzz::WebGPURequestDevice() {
  DVLOG(3) << "Requesting WebGPU device...";
  bool done = false;
  wgpu::DeviceDescriptor device_desc = {};
  device_desc.SetDeviceLostCallback(
      wgpu::CallbackMode::AllowSpontaneous,
      [](const wgpu::Device&, wgpu::DeviceLostReason reason,
         const char* message) {
        if (message) {
          DVLOG(3) << "***** Device lost: " << message << " *****";
        }
        if (reason == wgpu::DeviceLostReason::Destroyed) {
          return;
        }
        LOG(FATAL) << "Unexpected device lost (" << reason << "): " << message;
      });

  DCHECK(webgpu_adapter_);
  webgpu_adapter_.RequestDevice(&device_desc,
                                wgpu::CallbackMode::AllowSpontaneous,
                                [&](wgpu::RequestDeviceStatus status,
                                    wgpu::Device device, const char* message) {
                                  DVLOG(3) << "Attempting to acquire device";
                                  webgpu_device_ = std::move(device);
                                  DVLOG(3) << "Device acquired";
                                  done = true;
                                });
  webgpu()->FlushCommands();
  while (!done) {
    RunPendingTasks();
    base::PlatformThread::Sleep(kTinyTimeout);
  }
}

void CmdBufFuzz::WebGPUDestroyDevice() {
  DVLOG(3) << "Destroying device";
  webgpu_device_.Destroy();
  webgpu()->FlushCommands();
  WaitForCompletion(webgpu_instance_, webgpu_device_);
  DVLOG(3) << "Device destroyed? (see DeviceLostCallback log)";
}

void CmdBufFuzz::WebGPUCreateBuffer() {
  DVLOG(3) << "Creating WebGPU buffer";
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = 4;
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer buff = webgpu_device_.CreateBuffer(&buffer_desc);
  webgpu()->FlushCommands();
  WaitForCompletion(webgpu_instance_, webgpu_device_);
  wgpu_buffers_.push_back(std::move(buff));
  DVLOG(3) << "Created WebGPU buffer";
}

void CmdBufFuzz::WebGPUDestroyBuffer() {
  DVLOG(3) << "Destroying WebGPU buffer";
  for (wgpu::Buffer buff : wgpu_buffers_) {
    buff.Destroy();
  }
  wgpu_buffers_.clear();
  DVLOG(3) << "Destroyed WebGPU buffer";
  return;
}

void CmdBufFuzz::WebGPUReset() {
  // Let in-flight work finish.
  PollUntilIdle();
  // TODO: release & destroy buffer(s), device(s) & adapter(s).
}

}  // namespace gpu::cmdbuf::fuzzing