psemek/libs/wgpu/source/adapter.cpp
2023-12-30 16:50:44 +03:00

100 lines
3.5 KiB
C++

#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/external/webgpu.h>
#include <cstring>
namespace psemek::wgpu
{
std::vector<feature> adapter::enumerate_features()
{
std::size_t count = wgpuAdapterEnumerateFeatures((WGPUAdapter)get(), nullptr);
std::vector<feature> result(count);
wgpuAdapterEnumerateFeatures((WGPUAdapter)get(), (WGPUFeatureName *)result.data());
return result;
}
limits adapter::get_limits()
{
WGPUSupportedLimits limits = {};
wgpuAdapterGetLimits((WGPUAdapter)get(), &limits);
// TODO: support out chain
wgpu::limits result;
static_assert(sizeof(result) == sizeof(limits.limits));
std::memcpy(&result, &limits.limits, sizeof(result));
return result;
}
adapter::properties adapter::get_properties()
{
WGPUAdapterProperties props;
wgpuAdapterGetProperties((WGPUAdapter)get(), &props);
return {
.vendor_id = props.vendorID,
.vendor_name = props.vendorName,
.architecture = props.architecture,
.device_id = props.deviceID,
.name = props.name,
.driver_description = props.driverDescription,
.adapter_type = (adapter::type)props.adapterType,
.backend_type = (backend_type)props.backendType,
};
}
bool adapter::has_feature(feature feature)
{
return wgpuAdapterHasFeature((WGPUAdapter)get(), (WGPUFeatureName)feature);
}
void adapter::request_device(device::descriptor const & descriptor, device::request_callback const & callback)
{
WGPURequiredLimits limits = {};
if (descriptor.required_limits)
{
static_assert(sizeof(limits.limits) == sizeof(descriptor.required_limits->limits));
limits.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.required_limits->chain);
std::memcpy(&limits.limits, &descriptor.required_limits->limits, sizeof(limits.limits));
}
auto device_lost_userdata = new device::lost_callback(descriptor.lost_callback);
auto device_lost_real_callback = [](WGPUDeviceLostReason reason, char const * message, void * userdata)
{
std::unique_ptr<device::lost_callback> callback((device::lost_callback *)userdata);
if (*callback) (*callback)((device::lost_reason)reason, message ? message : "");
};
WGPUDeviceDescriptor device_desc = {};
device_desc.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.chain);
device_desc.label = descriptor.label.data();
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 = descriptor.default_queue.label.data();
device_desc.deviceLostCallback = device_lost_real_callback;
device_desc.deviceLostUserdata = device_lost_userdata;
auto userdata = new device::request_callback(callback);
auto real_callback = [](WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata)
{
std::unique_ptr<device::request_callback> callback{(device::request_callback *)userdata};
if (*callback) (*callback)((device::request_status)status, wgpu::device(device), message ? message : "");
};
wgpuAdapterRequestDevice((WGPUAdapter)get(), &device_desc, real_callback, userdata);
}
void adapter::reference(void * ptr)
{
wgpuAdapterReference((WGPUAdapter)ptr);
}
void adapter::release(void * ptr)
{
wgpuAdapterRelease((WGPUAdapter)ptr);
}
}