| // Copyright 2025 The Dawn & Tint Authors | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // 1. Redistributions of source code must retain the above copyright notice, this | |
| // list of conditions and the following disclaimer. | |
| // | |
| // 2. Redistributions in binary form must reproduce the above copyright notice, | |
| // this list of conditions and the following disclaimer in the documentation | |
| // and/or other materials provided with the distribution. | |
| // | |
| // 3. Neither the name of the copyright holder nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #include "src/dawn/native/webgpu/BackendWGPU.h" | |
| #include "dawn/dawn_proc_table.h" | |
| #include "src/dawn/native/Instance.h" | |
| #include "src/dawn/native/webgpu/PhysicalDeviceWGPU.h" | |
| namespace dawn::native::webgpu { | |
| Backend::Backend(InstanceBase* instance, wgpu::BackendType backendType) | |
| : BackendConnection(instance, backendType) { | |
| mDawnProcs = dawn::native::GetProcs(); | |
| // Enable all instance features and limits. | |
| WGPUInstanceDescriptor instanceDesc = WGPU_INSTANCE_DESCRIPTOR_INIT; | |
| WGPUDawnTogglesDescriptor toggleDescriptor = WGPU_DAWN_TOGGLES_DESCRIPTOR_INIT; | |
| instanceDesc.nextInChain = &toggleDescriptor.chain; | |
| auto toggles = instance->GetTogglesState(); | |
| auto enabledTogglesName = toggles.GetEnabledToggleNames(); | |
| toggleDescriptor.enabledToggleCount = enabledTogglesName.size(); | |
| toggleDescriptor.enabledToggles = enabledTogglesName.data(); | |
| auto disabledTogglesName = toggles.GetDisabledToggleNames(); | |
| toggleDescriptor.disabledToggleCount = disabledTogglesName.size(); | |
| toggleDescriptor.disabledToggles = disabledTogglesName.data(); | |
| WGPUSupportedInstanceFeatures features{}; | |
| mDawnProcs.getInstanceFeatures(&features); | |
| instanceDesc.requiredFeatureCount = features.featureCount; | |
| instanceDesc.requiredFeatures = features.features; | |
| WGPUInstanceLimits limits{}; | |
| mDawnProcs.getInstanceLimits(&limits); | |
| instanceDesc.requiredLimits = &limits; | |
| mInnerInstance = mDawnProcs.createInstance(&instanceDesc); | |
| mDawnProcs.supportedInstanceFeaturesFreeMembers(features); | |
| } | |
| Backend::~Backend() { | |
| if (mInnerInstance) { | |
| mDawnProcs.instanceRelease(mInnerInstance); | |
| mInnerInstance = nullptr; | |
| } | |
| } | |
| std::vector<Ref<PhysicalDeviceBase>> Backend::DiscoverPhysicalDevices( | |
| const UnpackedPtr<RequestAdapterOptions>& options) { | |
| // TODO(crbug.com/413053623): Expose Instance::EnumerateAdapters in DawnProcTable | |
| // So that we can discover multiple WebGPU physical devices. | |
| // Pass through all of the core options. Note if backendType=WebGPU, | |
| // RequestAdapter will return null since it's not enabled by default. | |
| WGPURequestAdapterOptions innerAdapterOption = *ToAPI(*options); | |
| // Get rid of the request adapter WebGPU backend options extension. | |
| // TODO(crbug.com/462137660): Implement for various extensions. | |
| innerAdapterOption.nextInChain = nullptr; | |
| // Keep DawnTogglesDescriptor. | |
| WGPUDawnTogglesDescriptor innerToggles = WGPU_DAWN_TOGGLES_DESCRIPTOR_INIT; | |
| if (auto* toggles = options.Get<DawnTogglesDescriptor>()) { | |
| innerToggles = *ToAPI(toggles); | |
| // Unchain any other extensions if exist. | |
| innerToggles.chain.next = nullptr; | |
| innerAdapterOption.nextInChain = &(innerToggles.chain); | |
| } | |
| WGPUAdapter innerAdapter = nullptr; | |
| WGPURequestAdapterCallbackInfo callbackInfo = {}; | |
| callbackInfo.mode = WGPUCallbackMode_WaitAnyOnly; | |
| callbackInfo.callback = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, | |
| WGPUStringView message, void* userdata1, void* userdata2) { | |
| if (status == WGPURequestAdapterStatus_Success) { | |
| *static_cast<WGPUAdapter*>(userdata2) = adapter; | |
| } | |
| }; | |
| callbackInfo.userdata1 = nullptr; | |
| callbackInfo.userdata2 = static_cast<void*>(&innerAdapter); | |
| WGPUFutureWaitInfo waitInfo = {}; | |
| waitInfo.future = | |
| mDawnProcs.instanceRequestAdapter(mInnerInstance, &innerAdapterOption, callbackInfo); | |
| mDawnProcs.instanceWaitAny(mInnerInstance, 1, &waitInfo, UINT64_MAX); | |
| if (innerAdapter == nullptr) { | |
| return {}; | |
| } | |
| return {PhysicalDevice::Create(this, innerAdapter)}; | |
| } | |
| const DawnProcTable& Backend::GetFunctions() const { | |
| return mDawnProcs; | |
| } | |
| WGPUInstance Backend::GetInnerInstance() const { | |
| return mInnerInstance; | |
| } | |
| BackendConnection* Connect(InstanceBase* instance) { | |
| return new Backend(instance, wgpu::BackendType::WebGPU); | |
| } | |
| } // namespace dawn::native::webgpu |