Issue with presenting a clear-color value with basic code in Dawn WebGPU (C API)

19 views
Skip to first unread message

Kalen White

unread,
Jan 10, 2025, 3:33:56 PMJan 10
to Dawn Graphics
Hello,

I noticed there are no webgpu examples in dawn repo, so may I ask where one can be found hosted at google or else-where?

I need to present the code that doesn't work, because I have tried 3 checkouts now across the StringView API change, and the Surface migration from SwapChain..  I am back to swap-chain because the last this worked for me, I was using swap-chain.  This commit is from July 22nd.

Appreciate the help.  This is C-based, for WebGPU API in Dawn.  I am building with the following args:

dawn https://dawn.googlesource.com/dawn 3764c82199cf0d39fd1d720a57d602f7b8407a91
-DDAWN_ENABLE_INSTALL=1
-DBUILD_SHARED_LIBS=0
-DTINT_BUILD_TESTS=0
-DDAWN_BUILD_SAMPLES=0
-DBUILD_SAMPLES=0



#include <GLFW/glfw3.h>
#if defined(_WIN32)
#include <windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#elif defined(__APPLE__)
#define GLFW_EXPOSE_NATIVE_COCOA
#elif defined(__linux__)
#define GLFW_EXPOSE_NATIVE_X11
#endif
#include <GLFW/glfw3native.h>
#include <dawn/webgpu.h>

#define LOG_PREFIX "[triangle]"

struct demo {
WGPUInstance instance;
WGPUSurface surface;
WGPUAdapter adapter;
WGPUDevice device;
WGPUSurfaceConfiguration config;
};

static void handle_request_adapter(WGPURequestAdapterStatus status,
WGPUAdapter adapter, const char* message,
void *userdata) {
if (status == WGPURequestAdapterStatus_Success) {
struct demo *demo = userdata;
demo->adapter = adapter;
} else {
printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status,
message);
}
}
static void handle_request_device(WGPURequestDeviceStatus status,
WGPUDevice device, const char* message,
void *userdata) {
if (status == WGPURequestDeviceStatus_Success) {
struct demo *demo = userdata;
demo->device = device;
} else {
printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status,
message);
}
}
static void handle_glfw_key(GLFWwindow *window, int key, int scancode,
int action, int mods) {
if (key == GLFW_KEY_R && (action == GLFW_PRESS || action == GLFW_REPEAT)) {
struct demo *demo = glfwGetWindowUserPointer(window);
if (!demo || !demo->instance)
return;
}
}
static void handle_glfw_framebuffer_size(GLFWwindow *window, int width,
int height) {
if (width == 0 && height == 0) {
return;
}

struct demo *demo = glfwGetWindowUserPointer(window);
if (!demo)
return;

demo->config.width = width;
demo->config.height = height;

wgpuSurfaceConfigure(demo->surface, &demo->config);
}

void print_adapter_info(WGPUAdapter adapter) {
struct WGPUAdapterInfo info = {0};
wgpuAdapterGetInfo(adapter, &info);
printf("description: %s\n", info.description);
printf("vendor: %s\n", info.vendor);
printf("architecture: %s\n", info.architecture);
printf("device: %s\n", info.device);
printf("backend type: %u\n", info.backendType);
printf("adapter type: %u\n", info.adapterType);
printf("vendorID: %x\n", info.vendorID);
printf("deviceID: %x\n", info.deviceID);
wgpuAdapterInfoFreeMembers(info);
}

void log_callback(WGPULoggingType level, char const* message, void* userdata) {
const char* level_str = "";
switch (level) {
case WGPULoggingType_Error: level_str = "Error"; break;
case WGPULoggingType_Warning: level_str = "Warn"; break;
case WGPULoggingType_Info: level_str = "Info"; break;
default: level_str = "Unknown"; break;
}
fprintf(stderr, "[%s] %s\n", level_str, message);
}
int main(int argc, char *argv[]) {
verify(glfwInit(), "glfw init");

struct demo demo = {0};
demo.instance = wgpuCreateInstance(NULL);
verify(demo.instance, "instance");

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow *window =
glfwCreateWindow(640, 480, "triangle [wgpu-native + glfw]", NULL, NULL);
verify(window, "window");

glfwSetWindowUserPointer(window, (void *)&demo);
glfwSetKeyCallback(window, handle_glfw_key);
glfwSetFramebufferSizeCallback(window, handle_glfw_framebuffer_size);

if (glfwGetPlatform() == GLFW_PLATFORM_X11) {
Display *x11_display = glfwGetX11Display();
Window x11_window = glfwGetX11Window(window);
demo.surface = wgpuInstanceCreateSurface(
demo.instance,
&(const WGPUSurfaceDescriptor){
.nextInChain =
(const WGPUChainedStruct *)&(
const WGPUSurfaceDescriptorFromXlibWindow){
.chain =
(const WGPUChainedStruct){
.sType = WGPUSType_SurfaceDescriptorFromXlibWindow,
},
.display = x11_display,
.window = x11_window,
},
});
}

wgpuInstanceProcessEvents(demo.instance);
verify(demo.surface, "surface");

wgpuInstanceRequestAdapter(demo.instance,
&(const WGPURequestAdapterOptions){
.compatibleSurface = demo.surface,
},
handle_request_adapter, &demo);
verify(demo.adapter, "adapter");

print_adapter_info(demo.adapter);

wgpuAdapterRequestDevice(demo.adapter, NULL, handle_request_device, &demo);
verify(demo.device, "device");

wgpuDeviceSetLoggingCallback(demo.device, log_callback, NULL);

WGPUQueue queue = wgpuDeviceGetQueue(demo.device);
verify(queue, "queue");

WGPUSurfaceCapabilities surface_capabilities = {0};
wgpuSurfaceGetCapabilities(demo.surface, demo.adapter, &surface_capabilities);

demo.config = (const WGPUSurfaceConfiguration){
.device = demo.device,
.usage = WGPUTextureUsage_RenderAttachment,
.format = WGPUTextureFormat_BGRA8Unorm,
.presentMode = WGPUPresentMode_Fifo, // Changed from Fifo
.alphaMode = WGPUCompositeAlphaMode_Opaque,
};

int width, height;
glfwGetWindowSize(window, &width, &height);
demo.config.width = width;
demo.config.height = height;

printf("Using format: %d\n", demo.config.format); // Debug print

WGPUSwapChain swap_chain = wgpuDeviceCreateSwapChain(demo.device, demo.surface, &(WGPUSwapChainDescriptor){
.label = "swap_chain",
.usage = WGPUTextureUsage_RenderAttachment,
.format = WGPUTextureFormat_BGRA8Unorm,
.presentMode = WGPUPresentMode_Fifo,
.width = demo.config.width,
.height = demo.config.height
});

while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
wgpuDeviceTick(demo.device); // ?

WGPUTextureView frame = wgpuSwapChainGetCurrentTextureView(swap_chain);

WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(
demo.device, &(WGPUCommandEncoderDescriptor){
.label = "Command Encoder",
});

WGPURenderPassEncoder render_pass = wgpuCommandEncoderBeginRenderPass(
encoder,
&(WGPURenderPassDescriptor){
.colorAttachmentCount = 1,
.colorAttachments = &(WGPURenderPassColorAttachment){
.view = frame,
.clearValue = (WGPUColor){
.r = 1.0f, // Changed to bright white for testing
.g = 1.0f,
.b = 1.0f,
.a = 1.0f,
},
},
});

wgpuRenderPassEncoderEnd(render_pass);
WGPUCommandBuffer commands = wgpuCommandEncoderFinish(
encoder, &(WGPUCommandBufferDescriptor){
.label = "Command Buffer",
});

wgpuQueueSubmit(queue, 1, &commands);
wgpuSwapChainPresent(swap_chain);

// Cleanup
wgpuCommandBufferRelease(commands);
wgpuRenderPassEncoderRelease(render_pass);
wgpuCommandEncoderRelease(encoder);
}

wgpuSurfaceCapabilitiesFreeMembers(surface_capabilities);
wgpuQueueRelease(queue);
wgpuDeviceRelease(demo.device);
wgpuAdapterRelease(demo.adapter);
wgpuSurfaceRelease(demo.surface);
glfwDestroyWindow(window);
wgpuInstanceRelease(demo.instance);
glfwTerminate();
return 0;
}


Corentin Wallez

unread,
Jan 15, 2025, 10:49:40 AMJan 15
to Kalen White, Dawn Graphics
Hey Kalen,

Dawn has a few samples, but to get started, the minimal code is probably https://github.com/beaufortfrancois/webgpu-cross-platform-app/.

Also make sure to have a device uncaptured error callback, so that Dawn validation errors are surfaced (there's likely one if you don't see anything on the window).

Hope this helps,

Corentin

--
You received this message because you are subscribed to the Google Groups "Dawn Graphics" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dawn-graphic...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/dawn-graphics/c7ac2cd8-ee27-4617-8c9e-5cf415ee6c06n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages