- Revision
- 290262
- Author
- mmaxfi...@apple.com
- Date
- 2022-02-21 12:49:00 -0800 (Mon, 21 Feb 2022)
Log Message
[WebGPU] Tracer bullet part 8: Basic implementation of device creation routines
https://bugs.webkit.org/show_bug.cgi?id=236902
Reviewed by Dean Jackson.
This is a basic implementation of the Instance, Adapter, and Device methods. Device limits are not
implemented yet, so for now we claim every limits is 0.
* WebGPU/Adapter.mm:
(WebGPU::Adapter::Adapter):
(WebGPU::Adapter::enumerateFeatures):
(WebGPU::Adapter::getLimits):
(WebGPU::Adapter::getProperties):
(WebGPU::Adapter::hasFeature):
(WebGPU::deviceMeetsRequiredLimits):
(WebGPU::Adapter::requestDevice):
* WebGPU/Device.h:
* WebGPU/Device.mm:
(WebGPU::Device::create):
(WebGPU::Device::Device):
(WebGPU::Device::destroy):
(WebGPU::Device::enumerateFeatures):
(WebGPU::Device::getLimits):
(WebGPU::Device::getQueue):
(WebGPU::Device::hasFeature):
(WebGPU::Device::popErrorScope):
(WebGPU::Device::pushErrorScope):
(WebGPU::Device::setDeviceLostCallback):
(WebGPU::Device::setUncapturedErrorCallback):
(WebGPU::Device::setLabel):
* WebGPU/Instance.mm:
(WebGPU::sortedDevices):
(WebGPU::Instance::requestAdapter):
Modified Paths
Diff
Modified: trunk/Source/WebGPU/ChangeLog (290261 => 290262)
--- trunk/Source/WebGPU/ChangeLog 2022-02-21 20:42:43 UTC (rev 290261)
+++ trunk/Source/WebGPU/ChangeLog 2022-02-21 20:49:00 UTC (rev 290262)
@@ -1,5 +1,41 @@
2022-02-21 Myles C. Maxfield <mmaxfi...@apple.com>
+ [WebGPU] Tracer bullet part 8: Basic implementation of device creation routines
+ https://bugs.webkit.org/show_bug.cgi?id=236902
+
+ Reviewed by Dean Jackson.
+
+ This is a basic implementation of the Instance, Adapter, and Device methods. Device limits are not
+ implemented yet, so for now we claim every limits is 0.
+
+ * WebGPU/Adapter.mm:
+ (WebGPU::Adapter::Adapter):
+ (WebGPU::Adapter::enumerateFeatures):
+ (WebGPU::Adapter::getLimits):
+ (WebGPU::Adapter::getProperties):
+ (WebGPU::Adapter::hasFeature):
+ (WebGPU::deviceMeetsRequiredLimits):
+ (WebGPU::Adapter::requestDevice):
+ * WebGPU/Device.h:
+ * WebGPU/Device.mm:
+ (WebGPU::Device::create):
+ (WebGPU::Device::Device):
+ (WebGPU::Device::destroy):
+ (WebGPU::Device::enumerateFeatures):
+ (WebGPU::Device::getLimits):
+ (WebGPU::Device::getQueue):
+ (WebGPU::Device::hasFeature):
+ (WebGPU::Device::popErrorScope):
+ (WebGPU::Device::pushErrorScope):
+ (WebGPU::Device::setDeviceLostCallback):
+ (WebGPU::Device::setUncapturedErrorCallback):
+ (WebGPU::Device::setLabel):
+ * WebGPU/Instance.mm:
+ (WebGPU::sortedDevices):
+ (WebGPU::Instance::requestAdapter):
+
+2022-02-21 Myles C. Maxfield <mmaxfi...@apple.com>
+
[WebGPU] Tracer bullet part 7: Clean up includes a bit
https://bugs.webkit.org/show_bug.cgi?id=236900
Modified: trunk/Source/WebGPU/WebGPU/Adapter.mm (290261 => 290262)
--- trunk/Source/WebGPU/WebGPU/Adapter.mm 2022-02-21 20:42:43 UTC (rev 290261)
+++ trunk/Source/WebGPU/WebGPU/Adapter.mm 2022-02-21 20:49:00 UTC (rev 290262)
@@ -34,38 +34,95 @@
Adapter::Adapter(id <MTLDevice> device)
: m_device(device)
{
- UNUSED_VARIABLE(m_device);
}
Adapter::~Adapter() = default;
-size_t Adapter::enumerateFeatures(WGPUFeatureName* features)
+size_t Adapter::enumerateFeatures(WGPUFeatureName*)
{
- UNUSED_PARAM(features);
+ // We support no optional features right now.
return 0;
}
bool Adapter::getLimits(WGPUSupportedLimits* limits)
{
- UNUSED_PARAM(limits);
+ if (limits->nextInChain != nullptr)
+ return false;
+
+ // FIXME: Implement this.
+ limits->limits = { };
return true;
}
void Adapter::getProperties(WGPUAdapterProperties* properties)
{
- UNUSED_PARAM(properties);
+ // FIXME: What should the vendorID and deviceID be?
+ properties->vendorID = 0;
+ properties->deviceID = 0;
+ properties->name = m_device.name.UTF8String;
+ properties->driverDescription = "";
+ properties->adapterType = m_device.hasUnifiedMemory ? WGPUAdapterType_IntegratedGPU : WGPUAdapterType_DiscreteGPU;
+ properties->backendType = WGPUBackendType_Metal;
}
-bool Adapter::hasFeature(WGPUFeatureName feature)
+bool Adapter::hasFeature(WGPUFeatureName)
{
- UNUSED_PARAM(feature);
+ // We support no optional features right now.
return false;
}
+static bool deviceMeetsRequiredLimits(id <MTLDevice>, const WGPURequiredLimits& requiredLimits)
+{
+ // FIXME: Implement this.
+ return !requiredLimits.nextInChain
+ && !requiredLimits.limits.maxTextureDimension1D
+ && !requiredLimits.limits.maxTextureDimension2D
+ && !requiredLimits.limits.maxTextureDimension3D
+ && !requiredLimits.limits.maxTextureArrayLayers
+ && !requiredLimits.limits.maxBindGroups
+ && !requiredLimits.limits.maxDynamicUniformBuffersPerPipelineLayout
+ && !requiredLimits.limits.maxDynamicStorageBuffersPerPipelineLayout
+ && !requiredLimits.limits.maxSampledTexturesPerShaderStage
+ && !requiredLimits.limits.maxSamplersPerShaderStage
+ && !requiredLimits.limits.maxStorageBuffersPerShaderStage
+ && !requiredLimits.limits.maxStorageTexturesPerShaderStage
+ && !requiredLimits.limits.maxUniformBuffersPerShaderStage
+ && !requiredLimits.limits.maxUniformBufferBindingSize
+ && !requiredLimits.limits.maxStorageBufferBindingSize
+ && !requiredLimits.limits.minUniformBufferOffsetAlignment
+ && !requiredLimits.limits.minStorageBufferOffsetAlignment
+ && !requiredLimits.limits.maxVertexBuffers
+ && !requiredLimits.limits.maxVertexAttributes
+ && !requiredLimits.limits.maxVertexBufferArrayStride
+ && !requiredLimits.limits.maxInterStageShaderComponents
+ && !requiredLimits.limits.maxComputeWorkgroupStorageSize
+ && !requiredLimits.limits.maxComputeInvocationsPerWorkgroup
+ && !requiredLimits.limits.maxComputeWorkgroupSizeX
+ && !requiredLimits.limits.maxComputeWorkgroupSizeY
+ && !requiredLimits.limits.maxComputeWorkgroupSizeZ
+ && !requiredLimits.limits.maxComputeWorkgroupsPerDimension;
+}
+
void Adapter::requestDevice(const WGPUDeviceDescriptor* descriptor, WTF::Function<void(WGPURequestDeviceStatus, RefPtr<Device>&&, const char*)>&& callback)
{
- UNUSED_PARAM(descriptor);
- UNUSED_PARAM(callback);
+ if (descriptor->nextInChain) {
+ callback(WGPURequestDeviceStatus_Error, nullptr, "Unknown descriptor type");
+ return;
+ }
+
+ if (descriptor->requiredFeaturesCount) {
+ callback(WGPURequestDeviceStatus_Error, nullptr, "Device does not support requested features");
+ return;
+ }
+
+ if (descriptor->requiredLimits && !deviceMeetsRequiredLimits(m_device, *descriptor->requiredLimits)) {
+ callback(WGPURequestDeviceStatus_Error, nullptr, "Device does not support requested limits");
+ return;
+ }
+
+ // See the comment in Device::setLabel() about why we're not setting the label here.
+
+ callback(WGPURequestDeviceStatus_Success, Device::create(m_device), nullptr);
}
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Device.h (290261 => 290262)
--- trunk/Source/WebGPU/WebGPU/Device.h 2022-02-21 20:42:43 UTC (rev 290261)
+++ trunk/Source/WebGPU/WebGPU/Device.h 2022-02-21 20:49:00 UTC (rev 290262)
@@ -83,9 +83,10 @@
void setLabel(const char*);
private:
- Device(id <MTLDevice>);
+ Device(id <MTLDevice>, Ref<Queue>&&);
id <MTLDevice> m_device { nil };
+ Ref<Queue> m_defaultQueue;
};
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Device.mm (290261 => 290262)
--- trunk/Source/WebGPU/WebGPU/Device.mm 2022-02-21 20:42:43 UTC (rev 290261)
+++ trunk/Source/WebGPU/WebGPU/Device.mm 2022-02-21 20:49:00 UTC (rev 290262)
@@ -47,13 +47,18 @@
RefPtr<Device> Device::create(id <MTLDevice> device)
{
- return adoptRef(*new Device(device));
+ id <MTLCommandQueue> commandQueue = [device newCommandQueue];
+ if (!commandQueue)
+ return nullptr;
+ auto queue = Queue::create(commandQueue);
+
+ return adoptRef(*new Device(device, WTFMove(queue)));
}
-Device::Device(id <MTLDevice> device)
+Device::Device(id <MTLDevice> device, Ref<Queue>&& queue)
: m_device(device)
+ , m_defaultQueue(WTFMove(queue))
{
- UNUSED_VARIABLE(m_device);
}
Device::~Device() = default;
@@ -60,33 +65,39 @@
void Device::destroy()
{
+ // FIXME: Implement this.
}
-size_t Device::enumerateFeatures(WGPUFeatureName* features)
+size_t Device::enumerateFeatures(WGPUFeatureName*)
{
- UNUSED_PARAM(features);
+ // We support no optional features right now.
return 0;
}
bool Device::getLimits(WGPUSupportedLimits* limits)
{
- UNUSED_PARAM(limits);
- return false;
+ if (limits->nextInChain != nullptr)
+ return false;
+
+ // FIXME: Implement this.
+ limits->limits = { };
+ return true;
}
RefPtr<Queue> Device::getQueue()
{
- return Queue::create(nil);
+ return m_defaultQueue.copyRef();
}
-bool Device::hasFeature(WGPUFeatureName feature)
+bool Device::hasFeature(WGPUFeatureName)
{
- UNUSED_PARAM(feature);
+ // We support no optional features right now.
return false;
}
bool Device::popErrorScope(WTF::Function<void(WGPUErrorType, const char*)>&& callback)
{
+ // FIXME: Implement this.
UNUSED_PARAM(callback);
return false;
}
@@ -93,22 +104,25 @@
void Device::pushErrorScope(WGPUErrorFilter filter)
{
+ // FIXME: Implement this.
UNUSED_PARAM(filter);
}
void Device::setDeviceLostCallback(WTF::Function<void(WGPUDeviceLostReason, const char*)>&& callback)
{
+ // FIXME: Implement this.
UNUSED_PARAM(callback);
}
void Device::setUncapturedErrorCallback(WTF::Function<void(WGPUErrorType, const char*)>&& callback)
{
+ // FIXME: Implement this.
UNUSED_PARAM(callback);
}
-void Device::setLabel(const char* label)
+void Device::setLabel(const char*)
{
- UNUSED_PARAM(label);
+ // Because MTLDevices are process-global, we can't set the label on it, because 2 contexts' labels would fight each other.
}
} // namespace WebGPU
Modified: trunk/Source/WebGPU/WebGPU/Instance.mm (290261 => 290262)
--- trunk/Source/WebGPU/WebGPU/Instance.mm 2022-02-21 20:42:43 UTC (rev 290261)
+++ trunk/Source/WebGPU/WebGPU/Instance.mm 2022-02-21 20:49:00 UTC (rev 290262)
@@ -74,11 +74,74 @@
} while (result);
}
+static NSArray<id <MTLDevice>> *sortedDevices(NSArray<id <MTLDevice>> *devices, WGPUPowerPreference powerPreference)
+{
+ switch (powerPreference) {
+ case WGPUPowerPreference_Undefined:
+ return devices;
+ case WGPUPowerPreference_LowPower:
+ return [devices sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult (id <MTLDevice> obj1, id <MTLDevice> obj2)
+ {
+ if (obj1.lowPower == obj2.lowPower)
+ return NSOrderedSame;
+ if (obj1.lowPower)
+ return NSOrderedAscending;
+ return NSOrderedDescending;
+ }];
+ case WGPUPowerPreference_HighPerformance:
+ return [devices sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult (id <MTLDevice> obj1, id <MTLDevice> obj2)
+ {
+ if (obj1.lowPower == obj2.lowPower)
+ return NSOrderedSame;
+ if (obj1.lowPower)
+ return NSOrderedDescending;
+ return NSOrderedAscending;
+ }];
+ default:
+ return nil;
+ }
+}
+
void Instance::requestAdapter(const WGPURequestAdapterOptions* options, WTF::Function<void(WGPURequestAdapterStatus, RefPtr<Adapter>&&, const char*)>&& callback)
{
- UNUSED_PARAM(options);
- UNUSED_PARAM(callback);
- callback(WGPURequestAdapterStatus_Unavailable, Adapter::create(nil), "Adapter");
+#if PLATFORM(MAC) || PLATFORM(MACCATALYST)
+ NSArray<id <MTLDevice>> *devices = MTLCopyAllDevices();
+#else
+ NSArray<id <MTLDevice>> *devices = [NSArray array];
+ if (id <MTLDevice> device = MTLCreateSystemDefaultDevice())
+ [devices append:device];
+#endif
+
+ // FIXME: Deal with options->compatibleSurface.
+
+ auto sortedDevices = WebGPU::sortedDevices(devices, options->powerPreference);
+
+ if (options->nextInChain) {
+ callback(WGPURequestAdapterStatus_Error, nullptr, "Unknown descriptor type");
+ return;
+ }
+
+ if (options->forceFallbackAdapter) {
+ callback(WGPURequestAdapterStatus_Unavailable, nullptr, "No adapters present");
+ return;
+ }
+
+ if (!sortedDevices) {
+ callback(WGPURequestAdapterStatus_Error, nullptr, "Unknown power preference");
+ return;
+ }
+
+ if (!sortedDevices.count) {
+ callback(WGPURequestAdapterStatus_Unavailable, nullptr, "No adapters present");
+ return;
+ }
+
+ if (!sortedDevices[0]) {
+ callback(WGPURequestAdapterStatus_Error, nullptr, "Adapter is internally null");
+ return;
+ }
+
+ callback(WGPURequestAdapterStatus_Success, Adapter::create(sortedDevices[0]), nullptr);
}
} // namespace WebGPU