Repository: google/filament
File: filament/backend/src/webgpu/platform/WebGPUPlatform.cpp (C++)

Code before:
                });
    }
    wgpu::Limits supportedLimits{};
    if (!device.GetLimits(&supportedLimits)) {
        FWGPU_LOGW << "Failed to get WebGPU supported device limits";
    } else {
        FWGPU_LOGI << "WebGPU device supported limits:";
        printLimits(supportedLimits);
    }
}
#endif

}// namespace

wgpu::Adapter WebGPUPlatform::requestAdapter(wgpu::Surface const& surface) {
    assertLimitsAreExpressedInRequirementsStruct();
    std::vector<wgpu::RequestAdapterOptions> requests = getAdapterOptions();
    for (auto& request: requests) {
        request.compatibleSurface = surface;
    }
    const std::unordered_set<AdapterDetails, AdapterDetailsHash> compatibleAdapters =
            requestCompatibleAdapters(mInstance, requests);
    return selectPreferredAdapter(compatibleAdapters);
}

wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) {
    std::vector<wgpu::FeatureName> enabledFeatures;
    enabledFeatures.reserve(REQUIRED_FEATURES.size() + OPTIONAL_FEATURES.size());
    for (auto const& requiredFeature : REQUIRED_FEATURES) {
        enabledFeatures.push_back(requiredFeature);
    }
    for (auto const& optionalFeature : OPTIONAL_FEATURES) {
        if (adapter.HasFeature(optionalFeature)) {
            enabledFeatures.push_back(optionalFeature);
        }
    }
    wgpu::DeviceDescriptor deviceDescriptor{};
    deviceDescriptor.label = "graphics_device";
    deviceDescriptor.defaultQueue.label = "default_queue";
    deviceDescriptor.requiredFeatureCount = enabledFeatures.size();
    deviceDescriptor.requiredFeatures = enabledFeatures.data();

    // It is helpful to increase maxStorageTexturesPerShaderStage if the hardware supports it, but
    // not required. If we have more cases like this we can generalize it in the future.
    wgpu::Limits supportedLimits{};
    adapter.GetLimits(&supportedLimits);
    auto actualLimits = REQUIRED_LIMITS;
    actualLimits.maxStorageTexturesPerShaderStage =
            std::min(12u, supportedLimits.maxStorageTexturesPerShaderStage);
    deviceDescriptor.requiredLimits = &actualLimits;


Review comment (suggestion):
We need to handle the case where `GetLimits(..)` returns/completes in error.

Code after:
    for (auto& request: requests) {
        request.compatibleSurface = surface;
    }
    const std::unordered_set<AdapterDetails, AdapterDetailsHash> compatibleAdapters =
            requestCompatibleAdapters(mInstance, requests);
    return selectPreferredAdapter(compatibleAdapters);
}

wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) {
    std::vector<wgpu::FeatureName> enabledFeatures;
    enabledFeatures.reserve(REQUIRED_FEATURES.size() + OPTIONAL_FEATURES.size());
    for (auto const& requiredFeature : REQUIRED_FEATURES) {
        enabledFeatures.push_back(requiredFeature);
    }
    for (auto const& optionalFeature : OPTIONAL_FEATURES) {
        if (adapter.HasFeature(optionalFeature)) {
            enabledFeatures.push_back(optionalFeature);
        }
    }
    wgpu::DeviceDescriptor deviceDescriptor{};
    deviceDescriptor.label = "graphics_device";
    deviceDescriptor.defaultQueue.label = "default_queue";
    deviceDescriptor.requiredFeatureCount = enabledFeatures.size();
    deviceDescriptor.requiredFeatures = enabledFeatures.data();

    // It is helpful to increase maxStorageTexturesPerShaderStage if the hardware supports it, but
    // not required. This allows our mipmap generation to perform as well as possible for the given
    // hardware. If we have more cases of "Nice to increase" limits like this we can generalize it
    // in the future.
    wgpu::Limits supportedLimits{};
    FILAMENT_CHECK_POSTCONDITION(
            adapter.GetLimits(&supportedLimits).status == wgpu::Status::Success)
            << "Failed to get limits for WebGPU adapter";
    auto limitsToRequest = REQUIRED_LIMITS;
    limitsToRequest.maxStorageTexturesPerShaderStage =
            std::min(MAX_MIPMAP_STORAGE_TEXTURES_PER_STAGE,
                    supportedLimits.maxStorageTexturesPerShaderStage);
    deviceDescriptor.requiredLimits = &limitsToRequest;

    deviceDescriptor.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
            [](wgpu::Device const&, wgpu::DeviceLostReason const& reason,
                    wgpu::StringView message) {
                if (reason == wgpu::DeviceLostReason::Destroyed) {
#if FWGPU_ENABLED(FWGPU_DEBUG_VALIDATION)
                    FWGPU_LOGD << "WebGPU device lost due to being destroyed (expected)";
#endif
                    return;
                }
                // TODO try recreating the device instead of just panicking
                FILAMENT_CHECK_POSTCONDITION(reason != wgpu::DeviceLostReason::Destroyed)
                        << "WebGPU device lost: " << deviceLostReasonToString(reason) << " "