#include 
  #include 
  #include <.. /webgpu/webgpu.h>
  #include 
  #include 
  #include 
  #include 
  
  WGPUAdapter requestAdapter(WGPUInstance instance, WGPURequestAdapterOptions const *options)
  {
  
    struct UserData
    {
      WGPUAdapter adapter = nullptr;
      bool requestEnded = false;
    };
    UserData userData;
  
    auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message,
                                    void *pUserData)
    {
                UserData& userData = *reinterpret_cast(pUserData);
                  if (status == WGPURequestAdapterStatus_Success) {
                  userData.adapter = adapter;
                  }
                  else {
                  std::cout << "Could not get WebGPU adapter: " << message << std::endl; } userData.requestEnded=true; };
    wgpuInstanceRequestAdapter(instance, options, onAdapterRequestEnded, (void *)&userData);
    assert(userData.requestEnded);
    return userData.adapter;
  }
  WGPUDevice requestDevice(WGPUAdapter
                               adapter,
                           WGPUDeviceDescriptor const *descriptor)
  {
    struct UserData
    {
      WGPUDevice device = nullptr;
      bool
          requestEnded = false;
    };
    UserData userData;
    auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status,
                                   WGPUDevice device, char const *message, void *pUserData)
    {
      UserData &
          userData = *reinterpret_cast(pUserData);
      if (status == WGPURequestDeviceStatus_Success)
      {
        userData.device = device;
      }
      else
      {
        std::cout << "Could not get WebGPU adapter: " << message << std::endl;
      }
      userData.requestEnded = true;
    };
    wgpuAdapterRequestDevice(adapter, descriptor, onDeviceRequestEnded, (void *)&userData);
    assert(userData.requestEnded);
    return userData.device;
  }
  int main(int, char **)
  { // instance
    ///////////////////////////////////////////////////////////////////////////////////
    WGPUInstanceDescriptor desc = {};
    desc.nextInChain = nullptr;
    WGPUInstance
        instance = wgpuCreateInstance(&desc);
    /////////////////////////////////////////////////////////////////////////////////// //window
    /////////////////////////////////////////////////////////////////////////////////// glfwInit(); if
    (!glfwInit())
    {
      std::cerr << "Could not initialize GLFW!" << std::endl;
      return 1;
    }
    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    GLFWwindow *window = glfwCreateWindow(640,
                                          480, "Learn WebGPU", NULL, NULL);
    if (!window)
    {
      std::cerr << "Could not open window!" << std::endl;
      glfwTerminate();
      return 1;
    }
    /////////////////////////////////////////////////////////////////////////////////// //adapter
    /////////////////////////////////////////////////////////////////////////////////// WGPUSurface
    surface = glfwGetWGPUSurface(instance, window);
    WGPURequestAdapterOptions adapterOpts = {};
    adapterOpts.nextInChain = nullptr;
    adapterOpts.compatibleSurface = surface;
    WGPUAdapter
        adapter = requestAdapter(instance, &adapterOpts);
    /////////////////////////////////////////////////////////////////////////////////// //device
    ///////////////////////////////////////////////////////////////////////////////////
    WGPUDeviceDescriptor deviceDesc = {};
    deviceDesc.nextInChain = nullptr;
    deviceDesc.label = "My Device";
    deviceDesc.requiredFeaturesCount = 0;
    deviceDesc.requiredLimits = nullptr;
    deviceDesc.defaultQueue.nextInChain = nullptr;
    deviceDesc.defaultQueue.label = "The default queue";
    WGPUDevice device = requestDevice(adapter, &deviceDesc);
    WGPUQueue queue = wgpuDeviceGetQueue(device);
    /////////////////////////////////////////////////////////////////////////////////// //swap chain
    ///////////////////////////////////////////////////////////////////////////////////
    WGPUSwapChainDescriptor swapChainDesc = {};
    swapChainDesc.width = 640;
    swapChainDesc.height = 480;
    swapChainDesc.usage = WGPUTextureUsage_RenderAttachment;
    WGPUTextureFormat
        swapChainFormat = wgpuSurfaceGetPreferredFormat(surface, adapter);
    swapChainDesc.format = swapChainFormat;
    swapChainDesc.presentMode = WGPUPresentMode_Fifo;
    WGPUSwapChain
        swapChain = wgpuDeviceCreateSwapChain(device, surface, &swapChainDesc);
    /////////////////////////////////////////////////////////////////////////////////// while
    (!glfwWindowShouldClose(window))
    {
      glfwPollEvents();
      WGPUTextureView
          nextTexture = wgpuSwapChainGetCurrentTextureView(swapChain); // encoder
      ///////////////////////////////////////////////////////////////////////////////////
      WGPUCommandEncoderDescriptor commandEncoderDesc = {};
      commandEncoderDesc.nextInChain = nullptr;
      commandEncoderDesc.label = "Command Encoder";
      WGPUCommandEncoder
          encoder = wgpuDeviceCreateCommandEncoder(device, &commandEncoderDesc);
      /////////////////////////////////////////////////////////////////////////////////// //Command queue
      ///////////////////////////////////////////////////////////////////////////////////
      WGPURenderPassDescriptor renderPassDesc = {};
      WGPURenderPassColorAttachment
          renderPassColorAttachment = {};
      renderPassColorAttachment.view = nextTexture;
      renderPassColorAttachment.resolveTarget = nullptr;
      renderPassColorAttachment.loadOp = WGPULoadOp_Clear;
      renderPassColorAttachment.storeOp = WGPUStoreOp_Store;
      renderPassColorAttachment.clearValue = WGPUColor{
          0.9, 0.1, 0.2, 1.0};
      renderPassDesc.colorAttachmentCount = 1;
      renderPassDesc.colorAttachments = &renderPassColorAttachment;
      renderPassDesc.depthStencilAttachment = nullptr;
      renderPassDesc.timestampWriteCount = 0;
      renderPassDesc.timestampWrites = nullptr;
      renderPassDesc.nextInChain = nullptr;
      WGPURenderPassEncoder
          renderPass = wgpuCommandEncoderBeginRenderPass(encoder, &renderPassDesc);
      wgpuRenderPassEncoderEnd(renderPass);
      wgpuTextureViewDrop(nextTexture);
      WGPUCommandBufferDescriptor
          cmdBufferDescriptor = {};
      cmdBufferDescriptor.nextInChain = nullptr;
      cmdBufferDescriptor.label = "Command buffer";
      WGPUCommandBuffer
          command = wgpuCommandEncoderFinish(encoder, &cmdBufferDescriptor);
      wgpuQueueSubmit(queue, 1,
                      &command);
      wgpuSwapChainPresent(swapChain);
      /////////////////////////////////////////////////////////////////////////////////// }
      glfwDestroyWindow(window);
      glfwTerminate();
      return 0;
    }