Cannot get 'clear color' of white to display, no real pipeline created yet

17 views
Skip to first unread message

Kalen White

unread,
Jan 10, 2025, 3:33:56 PMJan 10
to Dawn Graphics
// Problem: Cannot get 'clear color' of white to display
// I have implemented with dawn before, in C++
// Now I am attempting to implement the WebGPU API
// This, I successfully did with wgpu-native project, however
// I am having trouble implementing in Dawn

// building with a dawn from july 22nd
// have tried several others after october.
// this version does not require the String structure literal
// the adapter is chosen correctly though, and device is correct
// the surface is seemingly valid handle from XWindow
// no logging errors, and no faults occurring either.
// I have tried with and without the Surface API
// just went back to the SwapChain API now, in July

#include <A>
#include <GLFW/glfw3.h>
// currently implementing here
#if 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;
}
}
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;
}
}

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

WGPUShaderModule frmwrk_load_shader_module(WGPUDevice device,
const char *name) {
FILE *file = NULL;
char *buf = NULL;
WGPUShaderModule shader_module = NULL;

file = fopen(name, "rb");
if (!file) {
perror("fopen");
goto cleanup;
}

if (fseek(file, 0, SEEK_END) != 0) {
perror("fseek");
goto cleanup;
}
long length = ftell(file);
if (length == -1) {
perror("ftell");
goto cleanup;
}
if (fseek(file, 0, SEEK_SET) != 0) {
perror("fseek");
goto cleanup;
}

buf = calloc(1, length + 1);
fread(buf, 1, length, file);
buf[length] = 0;

shader_module = wgpuDeviceCreateShaderModule(
device, &(const WGPUShaderModuleDescriptor){
.label = name,
.nextInChain =
(const WGPUChainedStruct *)&(
const WGPUShaderModuleWGSLDescriptor){
.chain =
(const WGPUChainedStruct){
.sType = WGPUSType_ShaderModuleWGSLDescriptor,
},
.code = buf,
},
});

cleanup:
if (file)
fclose(file);
if (buf)
free(buf);
return shader_module;
}

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[]) {
A_start();
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 [webgpu-native + glfw]", NULL, NULL);
verify(window, "window");

glfwSetWindowUserPointer(window, (void *)&demo);
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");

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
//wgpuSurfaceConfigure(demo.surface, &demo.config);

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,
.loadOp = WGPULoadOp_Clear,
.storeOp = WGPUStoreOp_Store,
.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);
//wgpuSurfacePresent(demo.surface); /// do i still need this call? does it go above the prior?

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


Reply all
Reply to author
Forward
0 new messages