43#include <ufo/compute/compute.hpp>
56WGPUInstance createInstance(WGPUInstanceDescriptor
const* descriptor)
58 WGPUInstance instance = wgpuCreateInstance(descriptor);
59 assert(
nullptr != instance);
63WGPUAdapter createAdapter(WGPUInstance instance, WGPUSurface compatible_surface,
64 WGPUPowerPreference power_preference,
65 WGPUBackendType backend_type, WGPUBool force_fallback_adapter)
67 assert(
nullptr != instance);
69 WGPUAdapter adapter =
nullptr;
70 bool request_ended =
false;
72 WGPURequestAdapterOptions options = WGPU_REQUEST_ADAPTER_OPTIONS_INIT;
73 options.powerPreference = power_preference;
74 options.compatibleSurface = compatible_surface;
75 options.backendType = backend_type;
76 options.forceFallbackAdapter = force_fallback_adapter;
78 WGPURequestAdapterCallbackInfo callback_info = WGPU_REQUEST_ADAPTER_CALLBACK_INFO_INIT;
80 callback_info.callback = [](WGPURequestAdapterStatus status, WGPUAdapter adapter,
81 WGPUStringView message,
void* userdata1,
void* userdata2) {
82 if (WGPURequestAdapterStatus_Success == status) {
83 *
static_cast<WGPUAdapter*
>(userdata1) = adapter;
85 std::cerr <<
"Could not get WebGPU adapter: " << message.data << std::endl;
87 *
static_cast<bool*
>(userdata2) =
true;
89 callback_info.userdata1 =
static_cast<void*
>(&adapter);
90 callback_info.userdata2 =
static_cast<void*
>(&request_ended);
92 wgpuInstanceRequestAdapter(instance, &options, callback_info);
96 while (!request_ended) {
97 emscripten_sleep(100);
101 assert(request_ended);
102 assert(
nullptr != adapter);
107WGPUDevice createDevice(WGPUAdapter adapter, WGPULimits
const* required_limits)
109 assert(
nullptr != adapter);
111 WGPUDevice device =
nullptr;
112 bool request_ended =
false;
114 WGPUDeviceDescriptor desc = WGPU_DEVICE_DESCRIPTOR_INIT;
119 desc.requiredLimits = required_limits;
138 WGPURequestDeviceCallbackInfo callback_info = WGPU_REQUEST_DEVICE_CALLBACK_INFO_INIT;
140 callback_info.callback = [](WGPURequestDeviceStatus status, WGPUDevice device,
141 WGPUStringView message,
void* userdata1,
void* userdata2) {
142 if (WGPURequestDeviceStatus_Success == status) {
143 *
static_cast<WGPUDevice*
>(userdata1) = device;
145 std::cout <<
"Could not get WebGPU device: " << message.data << std::endl;
147 *
static_cast<bool*
>(userdata2) =
true;
149 callback_info.userdata1 =
static_cast<void*
>(&device);
150 callback_info.userdata2 =
static_cast<void*
>(&request_ended);
152 wgpuAdapterRequestDevice(adapter, &desc, callback_info);
156 while (!request_ended) {
157 emscripten_sleep(100);
161 assert(request_ended);
162 assert(
nullptr != device);
167WGPUQueue queue(WGPUDevice device)
169 assert(
nullptr != device);
170 return wgpuDeviceGetQueue(device);
173std::size_t bufferPaddedSize(std::size_t size)
175 static constexpr std::size_t
const COPY_BUFFER_ALIGNMENT = 4;
176 static constexpr std::size_t
const align_mask = COPY_BUFFER_ALIGNMENT - 1;
177 return std::max((size + align_mask) & ~align_mask, COPY_BUFFER_ALIGNMENT);
180std::size_t bufferPaddedSize(std::size_t width, std::size_t bytes_per_pixel)
182 static constexpr std::size_t
const COPY_BYTES_PER_ROW_ALIGNMENT = 256;
184 std::size_t
const unpadded_bytes_per_row = width * bytes_per_pixel;
185 std::size_t
const padded_bytes_per_row_padding =
186 (COPY_BYTES_PER_ROW_ALIGNMENT -
187 unpadded_bytes_per_row % COPY_BYTES_PER_ROW_ALIGNMENT) %
188 COPY_BYTES_PER_ROW_ALIGNMENT;
189 return unpadded_bytes_per_row + padded_bytes_per_row_padding;
192WGPUBuffer createBuffer(WGPUDevice device, std::string label, std::size_t size,
193 WGPUBufferUsage usage,
bool mapped_at_creation)
195 std::size_t padded_size = bufferPaddedSize(size);
197 WGPUBufferDescriptor desc = WGPU_BUFFER_DESCRIPTOR_INIT;
198 desc.label = {label.c_str(), label.length()};
199 desc.size = padded_size;
201 desc.mappedAtCreation = mapped_at_creation;
202 return wgpuDeviceCreateBuffer(device, &desc);
205WGPUBuffer createBufferInit(WGPUDevice device, std::string label, WGPUBufferUsage usage,
206 void* content, std::size_t content_size)
208 if (0 == content_size) {
209 return createBuffer(device, label, 0, usage,
false);
212 WGPUBuffer buffer = createBuffer(device, label, content_size, usage,
true);
214 assert(
nullptr != buffer);
216 void* buf = wgpuBufferGetMappedRange(buffer, 0, content_size);
217 std::memcpy(buf, content, content_size);
218 wgpuBufferUnmap(buffer);
223WGPUSurfaceCapabilities surfaceCapabilities(WGPUSurface surface, WGPUAdapter adapter)
225 WGPUSurfaceCapabilities surface_capabilities = WGPU_SURFACE_CAPABILITIES_INIT;
226 wgpuSurfaceGetCapabilities(surface, adapter, &surface_capabilities);
227 return surface_capabilities;
230WGPUShaderModule loadShaderModule(WGPUDevice device, std::filesystem::path
const& path)
232 std::ifstream file(path);
233 if (!file.is_open()) {
237 file.seekg(0, std::ios::end);
238 std::size_t size = file.tellg();
239 std::string shader_source(size,
' ');
241 file.read(shader_source.data(), size);
243 WGPUShaderSourceWGSL shader_wgsl = WGPU_SHADER_SOURCE_WGSL_INIT;
244 shader_wgsl.chain.sType = WGPUSType_ShaderSourceWGSL;
246 shader_wgsl.code = {shader_source.c_str(), WGPU_STRLEN};
248 WGPUShaderModuleDescriptor shader_desc = WGPU_SHADER_MODULE_DESCRIPTOR_INIT;
250 shader_desc.nextInChain =
reinterpret_cast<WGPUChainedStruct const*
>(&shader_wgsl);
252 return wgpuDeviceCreateShaderModule(device, &shader_desc);
257void release(WGPUInstance instance) { wgpuInstanceRelease(instance); }
259void release(WGPUSurface surface) { wgpuSurfaceRelease(surface); }
261void release(WGPUAdapter adapter) { wgpuAdapterRelease(adapter); }
263void release(WGPUDevice device) { wgpuDeviceRelease(device); }
265void release(WGPUQueue queue) { wgpuQueueRelease(queue); }
267void release(WGPUShaderModule shader_module) { wgpuShaderModuleRelease(shader_module); }
269void release(WGPUBindGroupLayout bind_group_layout)
271 wgpuBindGroupLayoutRelease(bind_group_layout);
274void release(WGPUPipelineLayout pipeline_layout)
276 wgpuPipelineLayoutRelease(pipeline_layout);
279void release(WGPURenderPipeline render_pipeline)
281 wgpuRenderPipelineRelease(render_pipeline);
284void release(WGPUTexture texture) { wgpuTextureRelease(texture); }
286void release(WGPUTextureView texture_view) { wgpuTextureViewRelease(texture_view); }
288void release(WGPURenderPassEncoder render_pass_encoder)
290 wgpuRenderPassEncoderRelease(render_pass_encoder);
293void release(WGPUCommandEncoder command_encoder)
295 wgpuCommandEncoderRelease(command_encoder);
298void release(WGPUCommandBuffer command_buffer)
300 wgpuCommandBufferRelease(command_buffer);
303void release(WGPUSampler sampler) { wgpuSamplerRelease(sampler); }
305GPUInfo gpuInfo(WGPUAdapter adapter)
307 bool const adapter_was_passed = (
nullptr != adapter);
309 WGPUInstance instance =
nullptr;
310 if (!adapter_was_passed) {
311 instance = createInstance();
312 if (
nullptr == instance) {
316 adapter = createAdapter(instance);
317 if (
nullptr == adapter) {
323 WGPUAdapterInfo info = {};
324 wgpuAdapterGetInfo(adapter, &info);
326 GPUInfo gpu_info = {};
327 gpu_info.name = std::string_view(info.device.data, info.device.length);
328 gpu_info.architecture =
329 std::string_view(info.architecture.data, info.architecture.length);
330 gpu_info.description = std::string_view(info.description.data, info.description.length);
332 gpu_info.vendor = [
id = info.vendorID, v = info.vendor.data] {
334 case 0x10DE:
return "NVIDIA";
335 case 0x1002:
return "AMD";
336 case 0x8086:
return "Intel";
337 case 0x13B5:
return "ARM";
338 case 0x5143:
return "Qualcomm";
339 case 0x106B:
return "Apple";
344 gpu_info.type = [t = info.adapterType] {
346 case WGPUAdapterType_DiscreteGPU:
return "Discrete GPU";
347 case WGPUAdapterType_IntegratedGPU:
return "Integrated GPU";
348 case WGPUAdapterType_CPU:
return "CPU";
349 case WGPUAdapterType_Unknown:
return "Unknown";
350 default:
return "Other";
354 gpu_info.backend = [
b = info.backendType] {
356 case WGPUBackendType_WebGPU:
return "WebGPU";
357 case WGPUBackendType_D3D11:
return "D3D11";
358 case WGPUBackendType_D3D12:
return "D3D12";
359 case WGPUBackendType_Metal:
return "Metal";
360 case WGPUBackendType_Vulkan:
return "Vulkan";
361 case WGPUBackendType_OpenGL:
return "OpenGL";
362 case WGPUBackendType_OpenGLES:
return "OpenGLES";
363 default:
return "Unknown";
367 wgpuAdapterInfoFreeMembers(info);
368 if (!adapter_was_passed) {
376std::vector<GPUInfo> gpusInfo()
378 WGPUInstance instance = createInstance();
379 if (
nullptr == instance) {
383 size_t count = wgpuInstanceEnumerateAdapters(instance,
nullptr,
nullptr);
389 std::vector<WGPUAdapter> adapters(count);
390 wgpuInstanceEnumerateAdapters(instance,
nullptr, adapters.data());
392 std::vector<GPUInfo> res;
394 for (
auto adapter : adapters) {
395 res.push_back(gpuInfo(adapter));
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.