// WGPU bind group builder - reduces boilerplate for bind group creation #pragma once #include // Forward declarations (users must include gpu.h) struct WGPUBindGroupLayoutEntry; struct WGPUBindGroupEntry; struct WGPUDeviceImpl; typedef struct WGPUDeviceImpl* WGPUDevice; struct WGPUBindGroupLayoutImpl; typedef struct WGPUBindGroupLayoutImpl* WGPUBindGroupLayout; struct WGPUBindGroupImpl; typedef struct WGPUBindGroupImpl* WGPUBindGroup; struct WGPUBufferImpl; typedef struct WGPUBufferImpl* WGPUBuffer; struct WGPUTextureViewImpl; typedef struct WGPUTextureViewImpl* WGPUTextureView; struct WGPUSamplerImpl; typedef struct WGPUSamplerImpl* WGPUSampler; typedef uint32_t WGPUShaderStageFlags; #include "platform/platform.h" class BindGroupLayoutBuilder { std::vector entries_; public: BindGroupLayoutBuilder& uniform(uint32_t binding, WGPUShaderStageFlags vis, size_t min_size = 0) { WGPUBindGroupLayoutEntry e{}; e.binding = binding; e.visibility = vis; e.buffer.type = WGPUBufferBindingType_Uniform; if (min_size) e.buffer.minBindingSize = min_size; entries_.push_back(e); return *this; } BindGroupLayoutBuilder& storage(uint32_t binding, WGPUShaderStageFlags vis, size_t min_size = 0) { WGPUBindGroupLayoutEntry e{}; e.binding = binding; e.visibility = vis; e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage; if (min_size) e.buffer.minBindingSize = min_size; entries_.push_back(e); return *this; } BindGroupLayoutBuilder& texture(uint32_t binding, WGPUShaderStageFlags vis) { WGPUBindGroupLayoutEntry e{}; e.binding = binding; e.visibility = vis; e.texture.sampleType = WGPUTextureSampleType_Float; e.texture.viewDimension = WGPUTextureViewDimension_2D; entries_.push_back(e); return *this; } BindGroupLayoutBuilder& sampler(uint32_t binding, WGPUShaderStageFlags vis) { WGPUBindGroupLayoutEntry e{}; e.binding = binding; e.visibility = vis; e.sampler.type = WGPUSamplerBindingType_Filtering; entries_.push_back(e); return *this; } WGPUBindGroupLayout build(WGPUDevice device) { WGPUBindGroupLayoutDescriptor desc{}; desc.entryCount = entries_.size(); desc.entries = entries_.data(); return wgpuDeviceCreateBindGroupLayout(device, &desc); } }; class BindGroupBuilder { std::vector entries_; public: BindGroupBuilder& buffer(uint32_t binding, WGPUBuffer buf, size_t size) { WGPUBindGroupEntry e{}; e.binding = binding; e.buffer = buf; e.size = size; entries_.push_back(e); return *this; } BindGroupBuilder& texture(uint32_t binding, WGPUTextureView view) { WGPUBindGroupEntry e{}; e.binding = binding; e.textureView = view; entries_.push_back(e); return *this; } BindGroupBuilder& sampler(uint32_t binding, WGPUSampler samp) { WGPUBindGroupEntry e{}; e.binding = binding; e.sampler = samp; entries_.push_back(e); return *this; } WGPUBindGroup build(WGPUDevice device, WGPUBindGroupLayout layout) { WGPUBindGroupDescriptor desc{}; desc.layout = layout; desc.entryCount = entries_.size(); desc.entries = entries_.data(); return wgpuDeviceCreateBindGroup(device, &desc); } };