#include #include #include #include #include #include #include typedef struct { SDL_Window* window; WGPUInstance instance; WGPUSurface surface; WGPUAdapter adapter; WGPUDevice device; WGPUQueue queue; } demo; void init_demo(demo* demo); void free_demo(demo* demo); int main() { demo demo = {0}; init_demo(&demo); SDL_Event e; bool running = true; while (running) { while (SDL_PollEvent(&e)) { if (e.type == SDL_EVENT_QUIT) { running = false; } } WGPUSurfaceTexture screenTexture; wgpuSurfaceGetCurrentTexture(demo.surface, &screenTexture); WGPUTextureView screenView = wgpuTextureCreateView(screenTexture.texture, NULL); WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(demo.device, &(const WGPUCommandEncoderDescriptor){ .label = {NULL, WGPU_STRLEN} }); WGPURenderPassEncoder renderPass = wgpuCommandEncoderBeginRenderPass(encoder, &(const WGPURenderPassDescriptor){ .label = {NULL, WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = &(const WGPURenderPassColorAttachment) { .view = screenView, .resolveTarget = NULL, .depthSlice = WGPU_DEPTH_SLICE_UNDEFINED, .loadOp = WGPULoadOp_Clear, .storeOp = WGPUStoreOp_Store, .clearValue = (WGPUColor) { .r = 0.1, .g = 0.2, .b = 0.3, .a = 1.0 } } }); wgpuRenderPassEncoderEnd(renderPass); wgpuRenderPassEncoderRelease(renderPass); WGPUCommandBuffer drawCommands = wgpuCommandEncoderFinish(encoder, NULL); wgpuQueueSubmit(demo.queue, 1, &drawCommands); wgpuSurfacePresent(demo.surface); wgpuCommandBufferRelease(drawCommands); wgpuCommandEncoderRelease(encoder); wgpuTextureViewRelease(screenView); wgpuTextureRelease(screenTexture.texture); } free_demo(&demo); SDL_Quit(); return 0; } void handle_adapter_request ( WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata, void* ) { demo* demo = userdata; if (status != WGPURequestAdapterStatus_Success) { SDL_Log("Failed to retreive wgpu adapter, error: %s, exitting!", message.data); exit(EXIT_FAILURE); } demo->adapter = adapter; } void handle_device_request ( WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata, void* ) { demo* demo = userdata; if (status != WGPURequestDeviceStatus_Success) { SDL_Log("Failed to retreive wgpu device, error: %s, exitting!", message.data); exit(EXIT_FAILURE); } demo->device = device; } void uncaptured_error_callback ( WGPUDevice const*, WGPUErrorType, WGPUStringView message, void*, void* ) { SDL_Log("Graphics Error: %s\n", message.data); } void init_demo(demo* demo) { demo->window = SDL_CreateWindow("WGPU Test", 800, 600, 0); demo->instance = wgpuCreateInstance(&(const WGPUInstanceDescriptor){ .requiredFeatureCount = 1, .requiredFeatures = (WGPUInstanceFeatureName[]){ WGPUInstanceFeatureName_TimedWaitAny } }); SDL_assert(demo->instance); #if defined(SDL_PLATFORM_LINUX) if (strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { Display* xdisplay = (Display*)SDL_GetPointerProperty(SDL_GetWindowProperties(demo->window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(demo->window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); if (xdisplay && xwindow) { demo->surface = wgpuInstanceCreateSurface(demo->instance, &(const WGPUSurfaceDescriptor){ .nextInChain = (WGPUChainedStruct*)&(WGPUSurfaceSourceXlibWindow) { .chain = (WGPUChainedStruct) { .next = NULL, .sType = WGPUSType_SurfaceSourceXlibWindow }, .display = xdisplay, .window = xwindow } }); } } #endif SDL_assert(demo->surface); WGPUFuture adapterFuture = wgpuInstanceRequestAdapter(demo->instance, &(const WGPURequestAdapterOptions){ .compatibleSurface = demo->surface, .powerPreference = WGPUPowerPreference_LowPower }, (WGPURequestAdapterCallbackInfo){ .callback = handle_adapter_request, .mode = WGPUCallbackMode_WaitAnyOnly, .userdata1 = demo }); wgpuInstanceWaitAny(demo->instance, 1, &(WGPUFutureWaitInfo){adapterFuture, false}, INT64_MAX); SDL_assert(demo->adapter); WGPUFuture deviceFuture = wgpuAdapterRequestDevice(demo->adapter, &(const WGPUDeviceDescriptor){ .label = {"RTX 2070", WGPU_STRLEN}, .uncapturedErrorCallbackInfo = { .callback = uncaptured_error_callback } }, (WGPURequestDeviceCallbackInfo){ .callback = handle_device_request, .mode = WGPUCallbackMode_WaitAnyOnly, .userdata1 = demo }); wgpuInstanceWaitAny(demo->instance, 1, &(WGPUFutureWaitInfo){deviceFuture, false}, INT64_MAX); SDL_assert(demo->device); WGPUSurfaceCapabilities caps; wgpuSurfaceGetCapabilities(demo->surface, demo->adapter, &caps); WGPUSurfaceConfiguration config = (WGPUSurfaceConfiguration) { .device = demo->device, .format = caps.formats[0], .usage = WGPUTextureUsage_RenderAttachment, .width = 800, .height = 600, .presentMode = WGPUPresentMode_Fifo, .alphaMode = caps.alphaModes[0] }; wgpuSurfaceConfigure(demo->surface, &config); demo->queue = wgpuDeviceGetQueue(demo->device); } void free_demo(demo* demo) { wgpuAdapterRelease(demo->adapter); wgpuSurfaceRelease(demo->surface); wgpuInstanceRelease(demo->instance); SDL_DestroyWindow(demo->window); }