#include #include #include #include #include namespace psemek::wgpu { std::vector adapter::enumerate_features() const { WGPUSupportedFeatures supported_features; wgpuAdapterGetFeatures((WGPUAdapter)get(), &supported_features); return std::vector((feature const *)supported_features.features, (feature const *)(supported_features.features) + supported_features.featureCount); } limits adapter::get_limits() const { WGPULimits limits = {}; detail::check_status("wgpuAdapterGetLimits", wgpuAdapterGetLimits((WGPUAdapter)get(), &limits)); // TODO: support out chain wgpu::limits result; result.max_texture_dimension_1D = limits.maxTextureDimension1D; result.max_texture_dimension_2D = limits.maxTextureDimension2D; result.max_texture_dimension_3D = limits.maxTextureDimension3D; result.max_texture_array_layers = limits.maxTextureArrayLayers; result.max_bind_groups = limits.maxBindGroups; result.max_bind_groups_plus_vertex_buffers = limits.maxBindGroupsPlusVertexBuffers; result.max_bindings_per_bind_group = limits.maxBindingsPerBindGroup; result.max_dynamic_uniform_buffers_per_pipeline_layout = limits.maxDynamicUniformBuffersPerPipelineLayout; result.max_dynamic_storage_buffers_per_pipeline_layout = limits.maxDynamicStorageBuffersPerPipelineLayout; result.max_sampled_textures_per_shader_stage = limits.maxSampledTexturesPerShaderStage; result.max_samplers_per_shader_stage = limits.maxSamplersPerShaderStage; result.max_storage_buffers_per_shader_stage = limits.maxStorageBuffersPerShaderStage; result.max_storage_textures_per_shader_stage = limits.maxStorageTexturesPerShaderStage; result.max_uniform_buffers_per_shader_stage = limits.maxUniformBuffersPerShaderStage; result.max_uniform_buffer_binding_size = limits.maxUniformBufferBindingSize; result.max_storage_buffer_binding_size = limits.maxStorageBufferBindingSize; result.min_uniform_buffer_offset_alignment = limits.minUniformBufferOffsetAlignment; result.min_storage_buffer_offset_alignment = limits.minStorageBufferOffsetAlignment; result.max_vertex_buffers = limits.maxVertexBuffers; result.max_buffer_size = limits.maxBufferSize; result.max_vertex_attributes = limits.maxVertexAttributes; result.max_vertex_buffer_array_stride = limits.maxVertexBufferArrayStride; result.max_inter_stage_shader_variables = limits.maxInterStageShaderVariables; result.max_color_attachments = limits.maxColorAttachments; result.max_color_attachment_bytes_per_sample = limits.maxColorAttachmentBytesPerSample; result.max_compute_workgroup_storage_size = limits.maxComputeWorkgroupStorageSize; result.max_compute_invocations_per_workgroup = limits.maxComputeInvocationsPerWorkgroup; result.max_compute_workgroup_size_x = limits.maxComputeWorkgroupSizeX; result.max_compute_workgroup_size_y = limits.maxComputeWorkgroupSizeY; result.max_compute_workgroup_size_z = limits.maxComputeWorkgroupSizeZ; result.max_compute_workgroups_per_dimension = limits.maxComputeWorkgroupsPerDimension; return result; } adapter::info adapter::get_info() const { WGPUAdapterInfo info; detail::check_status("wgpuAdapterGetInfo", wgpuAdapterGetInfo((WGPUAdapter)get(), &info)); return { .vendor = std::string_view(info.vendor.data, info.vendor.length), .architecture = std::string_view(info.architecture.data, info.architecture.length), .device = std::string_view(info.device.data, info.device.length), .description = std::string_view(info.description.data, info.description.length), .backend_type = (backend_type)info.backendType, .adapter_type = (type)info.adapterType, .vendor_id = info.vendorID, .device_id = info.deviceID, }; } bool adapter::has_feature(feature feature) const { return wgpuAdapterHasFeature((WGPUAdapter)get(), (WGPUFeatureName)feature); } void adapter::request_device(callback_mode mode, device::descriptor const & descriptor, device::request_callback const & callback) { WGPULimits limits = {}; if (descriptor.required_limits) { limits.nextInChain = (WGPUChainedStructOut *)detail::fill_chain_out(descriptor.required_limits->chain); limits.maxTextureDimension1D = descriptor.required_limits->limits.max_texture_dimension_1D; limits.maxTextureDimension2D = descriptor.required_limits->limits.max_texture_dimension_2D; limits.maxTextureDimension3D = descriptor.required_limits->limits.max_texture_dimension_3D; limits.maxTextureArrayLayers = descriptor.required_limits->limits.max_texture_array_layers; limits.maxBindGroups = descriptor.required_limits->limits.max_bind_groups; limits.maxBindGroupsPlusVertexBuffers = descriptor.required_limits->limits.max_bind_groups_plus_vertex_buffers; limits.maxBindingsPerBindGroup = descriptor.required_limits->limits.max_bindings_per_bind_group; limits.maxDynamicUniformBuffersPerPipelineLayout = descriptor.required_limits->limits.max_dynamic_uniform_buffers_per_pipeline_layout; limits.maxDynamicStorageBuffersPerPipelineLayout = descriptor.required_limits->limits.max_dynamic_storage_buffers_per_pipeline_layout; limits.maxSampledTexturesPerShaderStage = descriptor.required_limits->limits.max_sampled_textures_per_shader_stage; limits.maxSamplersPerShaderStage = descriptor.required_limits->limits.max_samplers_per_shader_stage; limits.maxStorageBuffersPerShaderStage = descriptor.required_limits->limits.max_storage_buffers_per_shader_stage; limits.maxStorageTexturesPerShaderStage = descriptor.required_limits->limits.max_storage_textures_per_shader_stage; limits.maxUniformBuffersPerShaderStage = descriptor.required_limits->limits.max_uniform_buffers_per_shader_stage; limits.maxUniformBufferBindingSize = descriptor.required_limits->limits.max_uniform_buffer_binding_size; limits.maxStorageBufferBindingSize = descriptor.required_limits->limits.max_storage_buffer_binding_size; limits.minUniformBufferOffsetAlignment = descriptor.required_limits->limits.min_uniform_buffer_offset_alignment; limits.minStorageBufferOffsetAlignment = descriptor.required_limits->limits.min_storage_buffer_offset_alignment; limits.maxVertexBuffers = descriptor.required_limits->limits.max_vertex_buffers; limits.maxBufferSize = descriptor.required_limits->limits.max_buffer_size; limits.maxVertexAttributes = descriptor.required_limits->limits.max_vertex_attributes; limits.maxVertexBufferArrayStride = descriptor.required_limits->limits.max_vertex_buffer_array_stride; limits.maxInterStageShaderVariables = descriptor.required_limits->limits.max_inter_stage_shader_variables; limits.maxColorAttachments = descriptor.required_limits->limits.max_color_attachments; limits.maxColorAttachmentBytesPerSample = descriptor.required_limits->limits.max_color_attachment_bytes_per_sample; limits.maxComputeWorkgroupStorageSize = descriptor.required_limits->limits.max_compute_workgroup_storage_size; limits.maxComputeInvocationsPerWorkgroup = descriptor.required_limits->limits.max_compute_invocations_per_workgroup; limits.maxComputeWorkgroupSizeX = descriptor.required_limits->limits.max_compute_workgroup_size_x; limits.maxComputeWorkgroupSizeY = descriptor.required_limits->limits.max_compute_workgroup_size_y; limits.maxComputeWorkgroupSizeZ = descriptor.required_limits->limits.max_compute_workgroup_size_z; limits.maxComputeWorkgroupsPerDimension = descriptor.required_limits->limits.max_compute_workgroups_per_dimension; } WGPUDeviceDescriptor device_desc = {}; device_desc.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.chain); device_desc.label = detail::to_string_view(descriptor.label); device_desc.requiredFeatureCount = descriptor.required_features.size(); device_desc.requiredFeatures = (WGPUFeatureName const *)descriptor.required_features.data(); device_desc.requiredLimits = descriptor.required_limits ? &limits : nullptr; device_desc.defaultQueue.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.default_queue.chain); device_desc.defaultQueue.label = detail::to_string_view(descriptor.default_queue.label); device_desc.deviceLostCallbackInfo.mode = (WGPUCallbackMode)descriptor.lost_callback_mode; device_desc.deviceLostCallbackInfo.callback = [](WGPUDevice const *, WGPUDeviceLostReason reason, WGPUStringView message, void * userdata, void *) { std::unique_ptr callback{(device::lost_callback *)userdata}; if (*callback) (*callback)((device::lost_reason)reason, std::string(message.data, message.length)); }; device_desc.deviceLostCallbackInfo.userdata1 = new device::lost_callback(descriptor.lost_callback); device_desc.uncapturedErrorCallbackInfo.callback = [](WGPUDevice const *, WGPUErrorType type, WGPUStringView message, void * userdata, void *) { auto callback = (device::uncaptured_error_callback *)userdata; if (*callback) (*callback)((error_type)type, std::string(message.data, message.length)); }; device_desc.uncapturedErrorCallbackInfo.userdata1 = new device::uncaptured_error_callback(descriptor.uncaptured_error_callback); WGPURequestDeviceCallbackInfo callback_info = {}; callback_info.mode = (WGPUCallbackMode)mode; callback_info.callback = [](WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void * userdata, void *) { std::unique_ptr callback{(device::request_callback *)userdata}; if (*callback) (*callback)((device::request_status)status, wgpu::device(device), std::string(message.data, message.length)); }; callback_info.userdata1 = new device::request_callback(callback); wgpuAdapterRequestDevice((WGPUAdapter)get(), &device_desc, callback_info); } void adapter::reference(void * ptr) { wgpuAdapterAddRef((WGPUAdapter)ptr); } void adapter::release(void * ptr) { wgpuAdapterRelease((WGPUAdapter)ptr); } }