text: // Copyright 2017 The Dawn Authors
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  #include "SampleUtils.h"
  
  #include "utils/SystemUtils.h"
  #include "utils/WGPUHelpers.h"
  
  WGPUDevice device;
  WGPUQueue queue;
  WGPUSwapChain swapchain;
  WGPURenderPipeline pipeline;
  
  WGPUTextureFormat swapChainFormat;
  
  void init() {
      device = CreateCppDawnDevice().Release();
      queue = wgpuDeviceCreateQueue(device);
  
      {
          WGPUSwapChainDescriptor descriptor;
          descriptor.nextInChain = nullptr;
          descriptor.label = nullptr;
          descriptor.implementation = GetSwapChainImplementation();
          swapchain = wgpuDeviceCreateSwapChain(device, &descriptor);
      }
      swapChainFormat = static_cast<WGPUTextureFormat>(GetPreferredSwapChainTextureFormat());
      wgpuSwapChainConfigure(swapchain, swapChainFormat, WGPUTextureUsage_OutputAttachment, 640, 480);
  
      const char* vs =
          "#version 450\n"
          "const vec2 pos[3] = vec2[3](vec2(0.0f, 0.5f), vec2(-0.5f, -0.5f), vec2(0.5f, -0.5f));\n"
          "void main() {\n"
          "   gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);\n"
          "}\n";
      WGPUShaderModule vsModule =
          utils::CreateShaderModule(wgpu::Device(device), utils::SingleShaderStage::Vertex, vs)
              .Release();
  
      const char* fs =
          "#version 450\n"
          "layout(location = 0) out vec4 fragColor;"
          "void main() {\n"
          "   fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
          "}\n";
      WGPUShaderModule fsModule =
          utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, fs).Release();
  
      {
          WGPURenderPipelineDescriptor descriptor;
          descriptor.label = nullptr;
          descriptor.nextInChain = nullptr;
  
          descriptor.vertexStage.nextInChain = nullptr;
          descriptor.vertexStage.module = vsModule;
          descriptor.vertexStage.entryPoint = "main";
  
          WGPUProgrammableStageDescriptor fragmentStage;
          fragmentStage.nextInChain = nullptr;
          fragmentStage.module = fsModule;
          fragmentStage.entryPoint = "main";
          descriptor.fragmentStage = &fragmentStage;
  
          descriptor.sampleCount = 1;
  
          WGPUBlendDescriptor blendDescriptor;
          blendDescriptor.operation = WGPUBlendOperation_Add;
          blendDescriptor.srcFactor = WGPUBlendFactor_One;
          blendDescriptor.dstFactor = WGPUBlendFactor_One;
          WGPUColorStateDescriptor colorStateDescriptor;
          colorStateDescriptor.nextInChain = nullptr;
          colorStateDescriptor.format = swapChainFormat;
          colorStateDescriptor.alphaBlend = blendDescriptor;
          colorStateDescriptor.colorBlend = blendDescriptor;
          colorStateDescriptor.writeMask = WGPUColorWriteMask_All;
  
          descriptor.colorStateCount = 1;
          descriptor.colorStates = &colorStateDescriptor;
  
          WGPUPipelineLayoutDescriptor pl;
          pl.nextInChain = nullptr;
          pl.label = nullptr;
          pl.bindGroupLayoutCount = 0;
          pl.bindGroupLayouts = nullptr;
          descriptor.layout = wgpuDeviceCreatePipelineLayout(device, &pl);
  
          WGPUVertexStateDescriptor vertexState;
          vertexState.nextInChain = nullptr;
          vertexState.indexFormat = WGPUIndexFormat_Uint32;
          vertexState.vertexBufferCount = 0;
          vertexState.vertexBuffers = nullptr;
          descriptor.vertexState = &vertexState;
  
          WGPURasterizationStateDescriptor rasterizationState;
          rasterizationState.nextInChain = nullptr;
          rasterizationState.frontFace = WGPUFrontFace_CCW;
          rasterizationState.cullMode = WGPUCullMode_None;
          rasterizationState.depthBias = 0;
          rasterizationState.depthBiasSlopeScale = 0.0;
          rasterizationState.depthBiasClamp = 0.0;
          descriptor.rasterizationState = &rasterizationState;
  
          descriptor.primitiveTopology = WGPUPrimitiveTopology_TriangleList;
          descriptor.sampleMask = 0xFFFFFFFF;
          descriptor.alphaToCoverageEnabled = false;
  
          descriptor.depthStencilState = nullptr;
  
          pipeline = wgpuDeviceCreateRenderPipeline(device, &descriptor);
      }
  
      wgpuShaderModuleRelease(vsModule);
      wgpuShaderModuleRelease(fsModule);
  }
  
  void frame() {
      WGPUTextureView backbufferView = wgpuSwapChainGetCurrentTextureView(swapchain);
      WGPURenderPassDescriptor renderpassInfo;
      renderpassInfo.nextInChain = nullptr;
      renderpassInfo.label = nullptr;
      WGPURenderPassColorAttachmentDescriptor colorAttachment;
      {
          colorAttachment.attachment = backbufferView;
          colorAttachment.resolveTarget = nullptr;
          colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
          colorAttachment.loadOp = WGPULoadOp_Clear;
          colorAttachment.storeOp = WGPUStoreOp_Store;
          renderpassInfo.colorAttachmentCount = 1;
          renderpassInfo.colorAttachments = &colorAttachment;
          renderpassInfo.depthStencilAttachment = nullptr;
      }
      WGPUCommandBuffer commands;
      {
          WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
  
          WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &renderpassInfo);
          wgpuRenderPassEncoderSetPipeline(pass, pipeline);
          wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0);
          wgpuRenderPassEncoderEndPass(pass);
          wgpuRenderPassEncoderRelease(pass);
  
          commands = wgpuCommandEncoderFinish(encoder, nullptr);
          wgpuCommandEncoderRelease(encoder);
      }
  
      wgpuQueueSubmit(queue, 1, &commands);
      wgpuCommandBufferRelease(commands);
      wgpuSwapChainPresent(swapchain);
      wgpuTextureViewRelease(backbufferView);
  
      DoFlush();
  }
  
  int main(int argc, const char* argv[]) {
      if (!InitSample(argc, argv)) {
          return 1;
      }
      init();
  
      while (!ShouldQuit()) {
          frame();
          utils::USleep(16000);
      }
  
      // TODO release stuff
  }
  