psemek/libs/wgpu/source/adapter.cpp

166 lines
9.8 KiB
C++

#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/detail/string_view.hpp>
#include <psemek/wgpu/detail/status.hpp>
#include <psemek/wgpu/external/webgpu.h>
#include <cstring>
namespace psemek::wgpu
{
std::vector<feature> adapter::enumerate_features() const
{
WGPUSupportedFeatures supported_features;
wgpuAdapterGetFeatures((WGPUAdapter)get(), &supported_features);
return std::vector<feature>((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<device::lost_callback> 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<device::request_callback> 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);
}
}