#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;
}