From 2f218e2b21b8f9cc00edcaf057fe48b56a12299e Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Wed, 22 Dec 2021 19:02:23 +0000 Subject: [PATCH] Implement upstream RequestDevice, add native-only CreateDevice This CL implements RequestDevice and also has changes for Dawn to internally use wgpu::FeatureName enums, instead of strings. Some of the string handling is kept for now to support the deprecated creation path. GetFeatureInfo is added to the instance to get a name and description of the feature, for reporting in about://gpu. Dawn device toggles are now passed in an extension struct off of the device descriptor. This is only supported in dawn_native, and not dawn_wire, for now, since dawn_wire doesn't have a way to serialize lists of null-terminated const char*. To enable the client to check whether the toggle descriptor is supported, a `dawn-native` feature is added which is supported all the time with dawn_native, but not supported with dawn_wire. Feature `dawn-native` also enables a synchronous version of CreateDevice for convenience. Bug: dawn:160 Change-Id: Ifc195e7ea808c6c319021528ef4b36bd65583bff Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/72020 Reviewed-by: Loko Kung Commit-Queue: Austin Eng --- dawn.json | 26 +++- dawn_wire.json | 1 + docs/features/dawn_native.md | 13 ++ generator/dawn_json_generator.py | 29 ++++- generator/templates/dawn_wire/WireCmd.cpp | 3 + src/dawn_native/Adapter.cpp | 95 +++++++-------- src/dawn_native/Adapter.h | 18 ++- src/dawn_native/DawnNative.cpp | 54 +++++++- src/dawn_native/Device.cpp | 47 +++---- src/dawn_native/Device.h | 7 +- src/dawn_native/Features.cpp | 59 +++++---- src/dawn_native/Features.h | 9 +- src/dawn_native/Instance.cpp | 13 +- src/dawn_native/Instance.h | 4 +- src/dawn_native/d3d12/AdapterD3D12.cpp | 2 +- src/dawn_native/d3d12/AdapterD3D12.h | 4 +- src/dawn_native/d3d12/DeviceD3D12.cpp | 6 +- src/dawn_native/d3d12/DeviceD3D12.h | 4 +- src/dawn_native/metal/BackendMTL.mm | 4 +- src/dawn_native/metal/DeviceMTL.h | 8 +- src/dawn_native/metal/DeviceMTL.mm | 10 +- src/dawn_native/null/DeviceNull.cpp | 15 ++- src/dawn_native/null/DeviceNull.h | 10 +- src/dawn_native/opengl/BackendGL.cpp | 4 +- src/dawn_native/opengl/DeviceGL.cpp | 10 +- src/dawn_native/opengl/DeviceGL.h | 8 +- src/dawn_native/vulkan/AdapterVk.cpp | 2 +- src/dawn_native/vulkan/AdapterVk.h | 4 +- src/dawn_native/vulkan/DeviceVk.cpp | 8 +- src/dawn_native/vulkan/DeviceVk.h | 6 +- src/dawn_wire/SupportedFeatures.cpp | 1 + src/dawn_wire/client/Adapter.cpp | 6 + src/dawn_wire/client/Adapter.h | 3 + src/include/dawn_native/DawnNative.h | 11 +- src/tests/BUILD.gn | 1 + src/tests/unittests/FeatureTests.cpp | 41 ++++--- src/tests/unittests/GetProcAddressTests.cpp | 2 +- src/tests/unittests/PerThreadProcTests.cpp | 4 +- .../unittests/native/DeviceCreationTests.cpp | 115 ++++++++++++++++++ .../VulkanImageWrappingTestsDmaBuf.cpp | 14 ++- .../VulkanImageWrappingTestsOpaqueFD.cpp | 14 ++- 41 files changed, 472 insertions(+), 223 deletions(-) create mode 100644 docs/features/dawn_native.md create mode 100644 src/tests/unittests/native/DeviceCreationTests.cpp diff --git a/dawn.json b/dawn.json index a575dcb6b3..6e9882b0dc 100644 --- a/dawn.json +++ b/dawn.json @@ -113,6 +113,14 @@ {"name": "callback", "type": "request device callback"}, {"name": "userdata", "type": "void", "annotation": "*"} ] + }, + { + "name": "create device", + "tags": ["dawn"], + "returns": "device", + "args": [ + {"name": "descriptor", "type": "device descriptor", "annotation": "const*", "optional": "true"} + ] } ] }, @@ -148,6 +156,17 @@ {"name": "required limits", "type": "required limits", "annotation": "const*", "optional": true} ] }, + "dawn toggles device descriptor": { + "tags": ["dawn", "native"], + "category": "structure", + "chained": "in", + "members": [ + {"name": "force enabled toggles count", "type": "uint32_t", "default": 0}, + {"name": "force enabled toggles", "type": "char", "annotation": "const*const*", "length": "force enabled toggles count"}, + {"name": "force disabled toggles count", "type": "uint32_t", "default": 0}, + {"name": "force disabled toggles", "type": "char", "annotation": "const*const*", "length": "force disabled toggles count"} + ] + }, "address mode": { "category": "enum", "values": [ @@ -1164,6 +1183,7 @@ {"name": "depth32 float stencil8", "type": "bool", "default": "false"}, {"name": "invalid feature", "type": "bool", "default": "false"}, {"name": "dawn internal usages", "type": "bool", "default": "false"}, + {"name": "dawn native", "type": "bool", "default": "false"}, {"name": "limits", "type": "supported limits"} ] }, @@ -1313,7 +1333,8 @@ {"value": 1000, "name": "depth clamping", "tags": ["emscripten", "dawn"]}, {"value": 1001, "name": "dawn shader float 16", "tags": ["dawn"]}, {"value": 1002, "name": "dawn internal usages", "tags": ["dawn"]}, - {"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]} + {"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]}, + {"value": 1004, "name": "dawn native", "tags": ["dawn", "native"]} ] }, "filter mode": { @@ -2347,7 +2368,8 @@ {"value": 10, "name": "external texture binding layout", "tags": ["dawn"]}, {"value": 11, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]}, {"value": 1000, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]}, - {"value": 1001, "name": "primitive depth clamping state", "tags": ["dawn", "emscripten"]} + {"value": 1001, "name": "primitive depth clamping state", "tags": ["dawn", "emscripten"]}, + {"value": 1002, "name": "dawn toggles device descriptor", "tags": ["dawn", "native"]} ] }, "texture": { diff --git a/dawn_wire.json b/dawn_wire.json index 497a0eb0f8..869f74bafd 100644 --- a/dawn_wire.json +++ b/dawn_wire.json @@ -179,6 +179,7 @@ "SurfaceDescriptorFromWindowsSwapChainPanel" ], "client_side_commands": [ + "AdapterCreateDevice", "AdapterGetProperties", "AdapterGetLimits", "AdapterHasFeature", diff --git a/docs/features/dawn_native.md b/docs/features/dawn_native.md new file mode 100644 index 0000000000..c1e212dae3 --- /dev/null +++ b/docs/features/dawn_native.md @@ -0,0 +1,13 @@ +# Dawn Native + +The `dawn-native` feature enables additional functionality that is supported only +when the WebGPU implementation is `dawn_native`. + +Additional functionality: + - `wgpu::DawnTogglesDeviceDescriptor` may be chained on `wgpu::DeviceDescriptor` on device creation to enable Dawn-specific toggles on the device. + + - Synchronous `adapter.CreateDevice(const wgpu::DeviceDescriptor*)` may be called. + +Notes: + - Enabling this feature in the `wgpu::DeviceDescriptor` does nothing, but +its presence in the Adapter's set of supported features means that the additional functionality is supported. diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py index 5c17d77549..fa8a1eea37 100644 --- a/generator/dawn_json_generator.py +++ b/generator/dawn_json_generator.py @@ -405,8 +405,10 @@ def topo_sort_structure(structs): return result -def parse_json(json, enabled_tags): - is_enabled = lambda json_data: item_is_enabled(enabled_tags, json_data) +def parse_json(json, enabled_tags, disabled_tags=None): + is_enabled = lambda json_data: item_is_enabled( + enabled_tags, json_data) and not item_is_disabled( + disabled_tags, json_data) category_to_parser = { 'bitmask': BitmaskType, 'enum': EnumType, @@ -426,7 +428,7 @@ def parse_json(json, enabled_tags): by_category[name] = [] for (name, json_data) in json.items(): - if name[0] == '_' or not item_is_enabled(enabled_tags, json_data): + if name[0] == '_' or not is_enabled(json_data): continue category = json_data['category'] parsed = category_to_parser[category](is_enabled, name, json_data) @@ -464,12 +466,14 @@ def parse_json(json, enabled_tags): 'types': types, 'by_category': by_category, 'enabled_tags': enabled_tags, + 'disabled_tags': disabled_tags, } return { 'metadata': Metadata(json['_metadata']), 'types': types, 'by_category': by_category, 'enabled_tags': enabled_tags, + 'disabled_tags': disabled_tags, 'c_methods': lambda typ: c_methods(api_params, typ), 'c_methods_sorted_by_name': get_c_methods_sorted_by_name(api_params), } @@ -617,6 +621,8 @@ def decorate(name, typ, arg): return typ + ' * ' + name elif arg.annotation == 'const*': return typ + ' const * ' + name + elif arg.annotation == 'const*const*': + return 'const ' + typ + '* const * ' + name else: assert False @@ -632,6 +638,14 @@ def item_is_enabled(enabled_tags, json_data): return any(tag in enabled_tags for tag in tags) +def item_is_disabled(disabled_tags, json_data): + if disabled_tags is None: return False + tags = json_data.get('tags') + if tags is None: return False + + return any(tag in disabled_tags for tag in tags) + + def as_cppEnum(value_name): assert not value_name.native if value_name.concatcase()[0].isdigit(): @@ -672,6 +686,7 @@ def c_methods(params, typ): Method(Name('release'), params['types']['void'], [], {'tags': ['dawn', 'emscripten']}), ] if item_is_enabled(params['enabled_tags'], x.json_data) + and not item_is_disabled(params['disabled_tags'], x.json_data) ] @@ -925,10 +940,14 @@ class MultiGeneratorFromDawnJSON(Generator): frontend_params)) if 'dawn_wire' in targets: - additional_params = compute_wire_params(params_dawn, wire_json) + params_dawn_wire = parse_json(loaded_json, + enabled_tags=['dawn', 'deprecated'], + disabled_tags=['native']) + additional_params = compute_wire_params(params_dawn_wire, + wire_json) wire_params = [ - RENDER_PARAMS_BASE, params_dawn, { + RENDER_PARAMS_BASE, params_dawn_wire, { 'as_wireType': lambda type : as_wireType(metadata, type), 'as_annotated_wireType': \ lambda arg: annotated(as_wireType(metadata, arg.type), arg), diff --git a/generator/templates/dawn_wire/WireCmd.cpp b/generator/templates/dawn_wire/WireCmd.cpp index 7bc148f6df..e473192898 100644 --- a/generator/templates/dawn_wire/WireCmd.cpp +++ b/generator/templates/dawn_wire/WireCmd.cpp @@ -179,6 +179,7 @@ {% endif %} { {% if member.annotation != "value" %} + {{ assert(member.annotation != "const*const*") }} auto memberLength = {{member_length(member, "record.")}}; result += memberLength * {{member_transfer_sizeof(member)}}; //* Structures might contain more pointers so we need to add their extra size as well. @@ -258,6 +259,7 @@ //* Allocate space and write the non-value arguments in it. {% for member in members if member.annotation != "value" and member.length != "strlen" and not member.skip_serialize %} + {{ assert(member.annotation != "const*const*") }} {% set memberName = as_varName(member.name) %} {% if member.type.category != "object" and member.optional %} @@ -367,6 +369,7 @@ //* Get extra buffer data, and copy pointed to values in extra allocated space. {% for member in members if member.annotation != "value" and member.length != "strlen" %} + {{ assert(member.annotation != "const*const*") }} {% set memberName = as_varName(member.name) %} {% if member.type.category != "object" and member.optional %} diff --git a/src/dawn_native/Adapter.cpp b/src/dawn_native/Adapter.cpp index 7ef85c1375..a30c553e97 100644 --- a/src/dawn_native/Adapter.cpp +++ b/src/dawn_native/Adapter.cpp @@ -15,12 +15,15 @@ #include "dawn_native/Adapter.h" #include "common/Constants.h" +#include "dawn_native/Device.h" #include "dawn_native/Instance.h" +#include "dawn_native/ValidationUtils_autogen.h" namespace dawn_native { AdapterBase::AdapterBase(InstanceBase* instance, wgpu::BackendType backend) : mInstance(instance), mBackend(backend) { + mSupportedFeatures.EnableFeature(Feature::DawnNative); mSupportedFeatures.EnableFeature(Feature::DawnInternalUsages); } @@ -90,10 +93,36 @@ namespace dawn_native { return mSupportedFeatures.EnumerateFeatures(features); } + DeviceBase* AdapterBase::APICreateDevice(const DeviceDescriptor* descriptor) { + DeviceDescriptor defaultDesc = {}; + if (descriptor == nullptr) { + descriptor = &defaultDesc; + } + auto result = CreateDeviceInternal(descriptor); + if (result.IsError()) { + mInstance->ConsumedError(result.AcquireError()); + return nullptr; + } + return result.AcquireSuccess().Detach(); + } + void AdapterBase::APIRequestDevice(const DeviceDescriptor* descriptor, WGPURequestDeviceCallback callback, void* userdata) { - callback(WGPURequestDeviceStatus_Error, nullptr, "Not implemented", userdata); + auto result = CreateDeviceInternal(descriptor); + + if (result.IsError()) { + std::unique_ptr errorData = result.AcquireError(); + callback(WGPURequestDeviceStatus_Error, nullptr, + errorData->GetFormattedMessage().c_str(), userdata); + return; + } + + Ref device = result.AcquireSuccess(); + + WGPURequestDeviceStatus status = + device == nullptr ? WGPURequestDeviceStatus_Unknown : WGPURequestDeviceStatus_Success; + callback(status, ToAPI(device.Detach()), nullptr, userdata); } wgpu::BackendType AdapterBase::GetBackendType() const { @@ -120,14 +149,10 @@ namespace dawn_native { return mSupportedFeatures; } - bool AdapterBase::SupportsAllRequestedFeatures( - const std::vector& requestedFeatures) const { - for (const char* featureStr : requestedFeatures) { - Feature featureEnum = mInstance->FeatureNameToEnum(featureStr); - if (featureEnum == Feature::InvalidEnum) { - return false; - } - if (!mSupportedFeatures.IsEnabled(featureEnum)) { + bool AdapterBase::SupportsAllRequiredFeatures( + const ityp::span& features) const { + for (wgpu::FeatureName f : features) { + if (!mSupportedFeatures.IsEnabled(f)) { return false; } } @@ -163,57 +188,27 @@ namespace dawn_native { return true; } - DeviceBase* AdapterBase::CreateDevice(const DawnDeviceDescriptor* descriptor) { - DeviceBase* result = nullptr; + ResultOrError> AdapterBase::CreateDeviceInternal( + const DeviceDescriptor* descriptor) { + ASSERT(descriptor != nullptr); - if (mInstance->ConsumedError(CreateDeviceInternal(&result, descriptor))) { - return nullptr; + for (uint32_t i = 0; i < descriptor->requiredFeaturesCount; ++i) { + wgpu::FeatureName f = descriptor->requiredFeatures[i]; + DAWN_TRY(ValidateFeatureName(f)); + DAWN_INVALID_IF(!mSupportedFeatures.IsEnabled(f), + "Requested feature %s is not supported.", f); } - return result; - } - - void AdapterBase::RequestDevice(const DawnDeviceDescriptor* descriptor, - WGPURequestDeviceCallback callback, - void* userdata) { - DeviceBase* device = nullptr; - MaybeError err = CreateDeviceInternal(&device, descriptor); - - if (err.IsError()) { - std::unique_ptr errorData = err.AcquireError(); - callback(WGPURequestDeviceStatus_Error, ToAPI(device), - errorData->GetFormattedMessage().c_str(), userdata); - return; - } - WGPURequestDeviceStatus status = - device == nullptr ? WGPURequestDeviceStatus_Unknown : WGPURequestDeviceStatus_Success; - callback(status, ToAPI(device), nullptr, userdata); - } - - MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result, - const DawnDeviceDescriptor* descriptor) { - if (descriptor != nullptr) { - for (const char* featureStr : descriptor->requiredFeatures) { - Feature featureEnum = mInstance->FeatureNameToEnum(featureStr); - DAWN_INVALID_IF(featureEnum == Feature::InvalidEnum, - "Requested feature %s is unknown.", featureStr); - DAWN_INVALID_IF(!mSupportedFeatures.IsEnabled(featureEnum), - "Requested feature %s is disabled.", featureStr); - } - } - - if (descriptor != nullptr && descriptor->requiredLimits != nullptr) { + if (descriptor->requiredLimits != nullptr) { DAWN_TRY_CONTEXT( ValidateLimits(mUseTieredLimits ? ApplyLimitTiers(mLimits.v1) : mLimits.v1, - FromAPI(descriptor->requiredLimits)->limits), + descriptor->requiredLimits->limits), "validating required limits"); DAWN_INVALID_IF(descriptor->requiredLimits->nextInChain != nullptr, "nextInChain is not nullptr."); } - - DAWN_TRY_ASSIGN(*result, CreateDeviceImpl(descriptor)); - return {}; + return CreateDeviceImpl(descriptor); } void AdapterBase::SetUseTieredLimits(bool useTieredLimits) { diff --git a/src/dawn_native/Adapter.h b/src/dawn_native/Adapter.h index a8a5fdb5f9..b8dc2d75c4 100644 --- a/src/dawn_native/Adapter.h +++ b/src/dawn_native/Adapter.h @@ -18,6 +18,7 @@ #include "dawn_native/DawnNative.h" #include "common/RefCounted.h" +#include "common/ityp_span.h" #include "dawn_native/Error.h" #include "dawn_native/Features.h" #include "dawn_native/Limits.h" @@ -44,6 +45,7 @@ namespace dawn_native { void APIRequestDevice(const DeviceDescriptor* descriptor, WGPURequestDeviceCallback callback, void* userdata); + DeviceBase* APICreateDevice(const DeviceDescriptor* descriptor = nullptr); wgpu::BackendType GetBackendType() const; wgpu::AdapterType GetAdapterType() const; @@ -51,16 +53,11 @@ namespace dawn_native { const PCIInfo& GetPCIInfo() const; InstanceBase* GetInstance() const; - DeviceBase* CreateDevice(const DawnDeviceDescriptor* descriptor = nullptr); - - void RequestDevice(const DawnDeviceDescriptor* descriptor, - WGPURequestDeviceCallback callback, - void* userdata); - void ResetInternalDeviceForTesting(); FeaturesSet GetSupportedFeatures() const; - bool SupportsAllRequestedFeatures(const std::vector& requestedFeatures) const; + bool SupportsAllRequiredFeatures( + const ityp::span& features) const; WGPUDeviceProperties GetAdapterProperties() const; bool GetLimits(SupportedLimits* limits) const; @@ -76,8 +73,8 @@ namespace dawn_native { FeaturesSet mSupportedFeatures; private: - virtual ResultOrError CreateDeviceImpl( - const DawnDeviceDescriptor* descriptor) = 0; + virtual ResultOrError> CreateDeviceImpl( + const DeviceDescriptor* descriptor) = 0; virtual MaybeError InitializeImpl() = 0; @@ -87,8 +84,7 @@ namespace dawn_native { // Check base WebGPU limits and populate supported limits. virtual MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) = 0; - MaybeError CreateDeviceInternal(DeviceBase** result, - const DawnDeviceDescriptor* descriptor); + ResultOrError> CreateDeviceInternal(const DeviceDescriptor* descriptor); virtual MaybeError ResetInternalDeviceForTestingImpl(); InstanceBase* mInstance = nullptr; diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp index c10fe0084d..86a6bb4653 100644 --- a/src/dawn_native/DawnNative.cpp +++ b/src/dawn_native/DawnNative.cpp @@ -14,6 +14,7 @@ #include "dawn_native/DawnNative.h" +#include "common/Log.h" #include "dawn_native/BindGroupLayout.h" #include "dawn_native/Buffer.h" #include "dawn_native/Device.h" @@ -25,6 +26,41 @@ namespace dawn_native { + namespace { + struct ComboDeprecatedDawnDeviceDescriptor : DeviceDescriptor { + ComboDeprecatedDawnDeviceDescriptor(const DawnDeviceDescriptor* deviceDescriptor) { + dawn::WarningLog() << "DawnDeviceDescriptor is deprecated. Please use " + "WGPUDeviceDescriptor instead."; + + DeviceDescriptor* desc = this; + + if (deviceDescriptor != nullptr) { + desc->nextInChain = &mTogglesDesc; + mTogglesDesc.forceEnabledToggles = deviceDescriptor->forceEnabledToggles.data(); + mTogglesDesc.forceEnabledTogglesCount = + deviceDescriptor->forceEnabledToggles.size(); + mTogglesDesc.forceDisabledToggles = + deviceDescriptor->forceDisabledToggles.data(); + mTogglesDesc.forceDisabledTogglesCount = + deviceDescriptor->forceDisabledToggles.size(); + + desc->requiredLimits = + reinterpret_cast(deviceDescriptor->requiredLimits); + + FeaturesInfo featuresInfo; + for (const char* featureStr : deviceDescriptor->requiredFeatures) { + mRequiredFeatures.push_back(featuresInfo.FeatureNameToAPIEnum(featureStr)); + } + desc->requiredFeatures = mRequiredFeatures.data(); + desc->requiredFeaturesCount = mRequiredFeatures.size(); + } + } + + DawnTogglesDeviceDescriptor mTogglesDesc = {}; + std::vector mRequiredFeatures = {}; + }; + } // namespace + const DawnProcTable& GetProcsAutogen(); const DawnProcTable& GetProcs() { @@ -98,6 +134,10 @@ namespace dawn_native { return mImpl->GetPCIInfo(); } + WGPUAdapter Adapter::Get() const { + return ToAPI(mImpl); + } + std::vector Adapter::GetSupportedFeatures() const { FeaturesSet supportedFeaturesSet = mImpl->GetSupportedFeatures(); return supportedFeaturesSet.GetEnabledFeatureNames(); @@ -124,13 +164,19 @@ namespace dawn_native { } WGPUDevice Adapter::CreateDevice(const DawnDeviceDescriptor* deviceDescriptor) { - return ToAPI(mImpl->CreateDevice(deviceDescriptor)); + ComboDeprecatedDawnDeviceDescriptor desc(deviceDescriptor); + return ToAPI(mImpl->APICreateDevice(&desc)); + } + + WGPUDevice Adapter::CreateDevice(const WGPUDeviceDescriptor* deviceDescriptor) { + return ToAPI(mImpl->APICreateDevice(FromAPI(deviceDescriptor))); } void Adapter::RequestDevice(const DawnDeviceDescriptor* descriptor, WGPURequestDeviceCallback callback, void* userdata) { - mImpl->RequestDevice(descriptor, callback, userdata); + ComboDeprecatedDawnDeviceDescriptor desc(descriptor); + mImpl->APIRequestDevice(&desc, callback, userdata); } void Adapter::ResetInternalDeviceForTesting() { @@ -176,6 +222,10 @@ namespace dawn_native { return mImpl->GetToggleInfo(toggleName); } + const FeatureInfo* Instance::GetFeatureInfo(WGPUFeatureName feature) { + return mImpl->GetFeatureInfo(static_cast(feature)); + } + void Instance::EnableBackendValidation(bool enableBackendValidation) { if (enableBackendValidation) { mImpl->SetBackendValidationLevel(BackendValidationLevel::Full); diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index 127b29f168..90af4cf00e 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -21,6 +21,7 @@ #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupLayout.h" #include "dawn_native/Buffer.h" +#include "dawn_native/ChainUtils_autogen.h" #include "dawn_native/CommandBuffer.h" #include "dawn_native/CommandEncoder.h" #include "dawn_native/CompilationMessages.h" @@ -172,15 +173,19 @@ namespace dawn_native { // DeviceBase - DeviceBase::DeviceBase(AdapterBase* adapter, const DawnDeviceDescriptor* descriptor) + DeviceBase::DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor) : mInstance(adapter->GetInstance()), mAdapter(adapter), mNextPipelineCompatibilityToken(1) { - if (descriptor != nullptr) { - ApplyToggleOverrides(descriptor); - ApplyFeatures(descriptor); - } + ASSERT(descriptor != nullptr); - if (descriptor != nullptr && descriptor->requiredLimits != nullptr) { - mLimits.v1 = ReifyDefaultLimits(FromAPI(descriptor->requiredLimits)->limits); + const DawnTogglesDeviceDescriptor* togglesDesc = nullptr; + FindInChain(descriptor->nextInChain, &togglesDesc); + if (togglesDesc != nullptr) { + ApplyToggleOverrides(togglesDesc); + } + ApplyFeatures(descriptor); + + if (descriptor->requiredLimits != nullptr) { + mLimits.v1 = ReifyDefaultLimits(descriptor->requiredLimits->limits); } else { GetDefaultLimits(&mLimits.v1); } @@ -1140,16 +1145,14 @@ namespace dawn_native { return result.Detach(); } - void DeviceBase::ApplyFeatures(const DawnDeviceDescriptor* deviceDescriptor) { + void DeviceBase::ApplyFeatures(const DeviceDescriptor* deviceDescriptor) { ASSERT(deviceDescriptor); - ASSERT(GetAdapter()->SupportsAllRequestedFeatures(deviceDescriptor->requiredFeatures)); + ASSERT(GetAdapter()->SupportsAllRequiredFeatures( + {deviceDescriptor->requiredFeatures, deviceDescriptor->requiredFeaturesCount})); - mEnabledFeatures = GetAdapter()->GetInstance()->FeatureNamesToFeaturesSet( - deviceDescriptor->requiredFeatures); - } - - std::vector DeviceBase::GetEnabledFeatures() const { - return mEnabledFeatures.GetEnabledFeatureNames(); + for (uint32_t i = 0; i < deviceDescriptor->requiredFeaturesCount; ++i) { + mEnabledFeatures.EnableFeature(deviceDescriptor->requiredFeatures[i]); + } } bool DeviceBase::IsFeatureEnabled(Feature feature) const { @@ -1600,18 +1603,20 @@ namespace dawn_native { SetToggle(Toggle::DisallowUnsafeAPIs, true); } - void DeviceBase::ApplyToggleOverrides(const DawnDeviceDescriptor* deviceDescriptor) { - ASSERT(deviceDescriptor); + void DeviceBase::ApplyToggleOverrides(const DawnTogglesDeviceDescriptor* togglesDescriptor) { + ASSERT(togglesDescriptor != nullptr); - for (const char* toggleName : deviceDescriptor->forceEnabledToggles) { - Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName); + for (uint32_t i = 0; i < togglesDescriptor->forceEnabledTogglesCount; ++i) { + Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum( + togglesDescriptor->forceEnabledToggles[i]); if (toggle != Toggle::InvalidEnum) { mEnabledToggles.Set(toggle, true); mOverridenToggles.Set(toggle, true); } } - for (const char* toggleName : deviceDescriptor->forceDisabledToggles) { - Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName); + for (uint32_t i = 0; i < togglesDescriptor->forceDisabledTogglesCount; ++i) { + Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum( + togglesDescriptor->forceDisabledToggles[i]); if (toggle != Toggle::InvalidEnum) { mEnabledToggles.Set(toggle, false); mOverridenToggles.Set(toggle, true); diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 298d0b47ac..192547806d 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -56,7 +56,7 @@ namespace dawn_native { class DeviceBase : public RefCounted { public: - DeviceBase(AdapterBase* adapter, const DawnDeviceDescriptor* descriptor); + DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor); virtual ~DeviceBase(); void HandleError(InternalErrorType type, const char* message); @@ -312,7 +312,6 @@ namespace dawn_native { void TrackObject(ApiObjectBase* object); std::mutex* GetObjectListMutex(ObjectType type); - std::vector GetEnabledFeatures() const; std::vector GetTogglesUsed() const; bool IsFeatureEnabled(Feature feature) const; bool IsToggleEnabled(Toggle toggle) const; @@ -442,8 +441,8 @@ namespace dawn_native { WGPUCreateRenderPipelineAsyncCallback callback, void* userdata); - void ApplyToggleOverrides(const DawnDeviceDescriptor* deviceDescriptor); - void ApplyFeatures(const DawnDeviceDescriptor* deviceDescriptor); + void ApplyToggleOverrides(const DawnTogglesDeviceDescriptor* togglesDescriptor); + void ApplyFeatures(const DeviceDescriptor* deviceDescriptor); void SetDefaultToggles(); diff --git a/src/dawn_native/Features.cpp b/src/dawn_native/Features.cpp index 037d8f4248..913706ceaf 100644 --- a/src/dawn_native/Features.cpp +++ b/src/dawn_native/Features.cpp @@ -83,7 +83,12 @@ namespace dawn_native { {"multiplanar-formats", "Import and use multi-planar texture formats with per plane views", "https://bugs.chromium.org/p/dawn/issues/detail?id=551"}, - &WGPUDeviceProperties::multiPlanarFormats}}}; + &WGPUDeviceProperties::multiPlanarFormats}, + {Feature::DawnNative, + {"dawn-native", "WebGPU is running on top of dawn_native.", + "https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/features/" + "dawn_native.md"}, + &WGPUDeviceProperties::dawnNative}}}; Feature FromAPIFeature(wgpu::FeatureName feature) { switch (feature) { @@ -112,6 +117,8 @@ namespace dawn_native { return Feature::DawnInternalUsages; case wgpu::FeatureName::DawnMultiPlanarFormats: return Feature::MultiPlanarFormats; + case wgpu::FeatureName::DawnNative: + return Feature::DawnNative; case wgpu::FeatureName::IndirectFirstInstance: return Feature::InvalidEnum; @@ -143,6 +150,8 @@ namespace dawn_native { return wgpu::FeatureName::DawnInternalUsages; case Feature::MultiPlanarFormats: return wgpu::FeatureName::DawnMultiPlanarFormats; + case Feature::DawnNative: + return wgpu::FeatureName::DawnNative; case Feature::EnumCount: UNREACHABLE(); @@ -157,6 +166,10 @@ namespace dawn_native { featuresBitSet.set(featureIndex); } + void FeaturesSet::EnableFeature(wgpu::FeatureName feature) { + EnableFeature(FromAPIFeature(feature)); + } + bool FeaturesSet::IsEnabled(Feature feature) const { ASSERT(feature != Feature::InvalidEnum); const size_t featureIndex = static_cast(feature); @@ -184,8 +197,13 @@ namespace dawn_native { uint32_t index = 0; for (uint32_t i : IterateBitSet(featuresBitSet)) { - const char* featureName = FeatureEnumToName(static_cast(i)); - enabledFeatureNames[index] = featureName; + Feature feature = static_cast(i); + ASSERT(feature != Feature::InvalidEnum); + + const FeatureEnumAndInfo& featureNameAndInfo = kFeatureNameAndInfoList[i]; + ASSERT(featureNameAndInfo.feature == feature); + + enabledFeatureNames[index] = featureNameAndInfo.info.name; ++index; } return enabledFeatureNames; @@ -199,13 +217,9 @@ namespace dawn_native { } } - const char* FeatureEnumToName(Feature feature) { + wgpu::FeatureName FeatureEnumToAPIFeature(Feature feature) { ASSERT(feature != Feature::InvalidEnum); - - const FeatureEnumAndInfo& featureNameAndInfo = - kFeatureNameAndInfoList[static_cast(feature)]; - ASSERT(featureNameAndInfo.feature == feature); - return featureNameAndInfo.info.name; + return ToAPIFeature(feature); } FeaturesInfo::FeaturesInfo() { @@ -216,14 +230,12 @@ namespace dawn_native { } } - const FeatureInfo* FeaturesInfo::GetFeatureInfo(const char* featureName) const { - ASSERT(featureName); - - const auto& iter = mFeatureNameToEnumMap.find(featureName); - if (iter != mFeatureNameToEnumMap.cend()) { - return &kFeatureNameAndInfoList[static_cast(iter->second)].info; + const FeatureInfo* FeaturesInfo::GetFeatureInfo(wgpu::FeatureName feature) const { + Feature f = FromAPIFeature(feature); + if (f == Feature::InvalidEnum) { + return nullptr; } - return nullptr; + return &kFeatureNameAndInfoList[static_cast(f)].info; } Feature FeaturesInfo::FeatureNameToEnum(const char* featureName) const { @@ -253,16 +265,13 @@ namespace dawn_native { return Feature::InvalidEnum; } - FeaturesSet FeaturesInfo::FeatureNamesToFeaturesSet( - const std::vector& requiredFeatures) const { - FeaturesSet featuresSet; - - for (const char* featureName : requiredFeatures) { - Feature featureEnum = FeatureNameToEnum(featureName); - ASSERT(featureEnum != Feature::InvalidEnum); - featuresSet.EnableFeature(featureEnum); + wgpu::FeatureName FeaturesInfo::FeatureNameToAPIEnum(const char* featureName) const { + Feature f = FeatureNameToEnum(featureName); + if (f != Feature::InvalidEnum) { + return ToAPIFeature(f); } - return featuresSet; + // Pass something invalid. + return static_cast(-1); } } // namespace dawn_native diff --git a/src/dawn_native/Features.h b/src/dawn_native/Features.h index 6dd2afc30f..07a1e6d19a 100644 --- a/src/dawn_native/Features.h +++ b/src/dawn_native/Features.h @@ -39,6 +39,7 @@ namespace dawn_native { // Dawn-specific DawnInternalUsages, MultiPlanarFormats, + DawnNative, EnumCount, InvalidEnum = EnumCount, @@ -51,6 +52,7 @@ namespace dawn_native { std::bitset(Feature::EnumCount)> featuresBitSet; void EnableFeature(Feature feature); + void EnableFeature(wgpu::FeatureName feature); bool IsEnabled(Feature feature) const; bool IsEnabled(wgpu::FeatureName feature) const; // Returns |count|, the number of features. Writes out all |count| values if |features| is @@ -60,7 +62,7 @@ namespace dawn_native { void InitializeDeviceProperties(WGPUDeviceProperties* properties) const; }; - const char* FeatureEnumToName(Feature feature); + wgpu::FeatureName FeatureEnumToAPIFeature(Feature feature); class FeaturesInfo { public: @@ -68,10 +70,9 @@ namespace dawn_native { // Used to query the details of an feature. Return nullptr if featureName is not a valid // name of an feature supported in Dawn - const FeatureInfo* GetFeatureInfo(const char* featureName) const; + const FeatureInfo* GetFeatureInfo(wgpu::FeatureName feature) const; Feature FeatureNameToEnum(const char* featureName) const; - FeaturesSet FeatureNamesToFeaturesSet( - const std::vector& requiredFeatures) const; + wgpu::FeatureName FeatureNameToAPIEnum(const char* featureName) const; private: std::unordered_map mFeatureNameToEnumMap; diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp index d8e107f8f7..39648f38c4 100644 --- a/src/dawn_native/Instance.cpp +++ b/src/dawn_native/Instance.cpp @@ -142,17 +142,8 @@ namespace dawn_native { return mTogglesInfo.ToggleNameToEnum(toggleName); } - const FeatureInfo* InstanceBase::GetFeatureInfo(const char* featureName) { - return mFeaturesInfo.GetFeatureInfo(featureName); - } - - Feature InstanceBase::FeatureNameToEnum(const char* featureName) { - return mFeaturesInfo.FeatureNameToEnum(featureName); - } - - FeaturesSet InstanceBase::FeatureNamesToFeaturesSet( - const std::vector& requiredFeatures) { - return mFeaturesInfo.FeatureNamesToFeaturesSet(requiredFeatures); + const FeatureInfo* InstanceBase::GetFeatureInfo(wgpu::FeatureName feature) { + return mFeaturesInfo.GetFeatureInfo(feature); } const std::vector>& InstanceBase::GetAdapters() const { diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h index a36255aa62..488a30e3a8 100644 --- a/src/dawn_native/Instance.h +++ b/src/dawn_native/Instance.h @@ -64,9 +64,7 @@ namespace dawn_native { // Used to query the details of an feature. Return nullptr if featureName is not a valid // name of an feature supported in Dawn. - const FeatureInfo* GetFeatureInfo(const char* featureName); - Feature FeatureNameToEnum(const char* featureName); - FeaturesSet FeatureNamesToFeaturesSet(const std::vector& requiredFeatures); + const FeatureInfo* GetFeatureInfo(wgpu::FeatureName feature); bool IsBackendValidationEnabled() const; void SetBackendValidationLevel(BackendValidationLevel level); diff --git a/src/dawn_native/d3d12/AdapterD3D12.cpp b/src/dawn_native/d3d12/AdapterD3D12.cpp index ca845f3ad2..6e40c7a242 100644 --- a/src/dawn_native/d3d12/AdapterD3D12.cpp +++ b/src/dawn_native/d3d12/AdapterD3D12.cpp @@ -394,7 +394,7 @@ namespace dawn_native { namespace d3d12 { infoQueue->PopStorageFilter(); } - ResultOrError Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) { + ResultOrError> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { return Device::Create(this, descriptor); } diff --git a/src/dawn_native/d3d12/AdapterD3D12.h b/src/dawn_native/d3d12/AdapterD3D12.h index 4f404479dc..4bb5a02045 100644 --- a/src/dawn_native/d3d12/AdapterD3D12.h +++ b/src/dawn_native/d3d12/AdapterD3D12.h @@ -40,8 +40,8 @@ namespace dawn_native { namespace d3d12 { const gpu_info::D3DDriverVersion& GetDriverVersion() const; private: - ResultOrError CreateDeviceImpl( - const DawnDeviceDescriptor* descriptor) override; + ResultOrError> CreateDeviceImpl( + const DeviceDescriptor* descriptor) override; MaybeError ResetInternalDeviceForTestingImpl() override; bool AreTimestampQueriesSupported() const; diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp index 210478934a..94697e2626 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -56,11 +56,11 @@ namespace dawn_native { namespace d3d12 { static constexpr uint64_t kMaxDebugMessagesToPrint = 5; // static - ResultOrError Device::Create(Adapter* adapter, - const DawnDeviceDescriptor* descriptor) { + ResultOrError> Device::Create(Adapter* adapter, + const DeviceDescriptor* descriptor) { Ref device = AcquireRef(new Device(adapter, descriptor)); DAWN_TRY(device->Initialize()); - return device.Detach(); + return device; } MaybeError Device::Initialize() { diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h index e6b7234711..6036e41a45 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.h +++ b/src/dawn_native/d3d12/DeviceD3D12.h @@ -41,8 +41,8 @@ namespace dawn_native { namespace d3d12 { // Definition of backend types class Device final : public DeviceBase { public: - static ResultOrError Create(Adapter* adapter, - const DawnDeviceDescriptor* descriptor); + static ResultOrError> Create(Adapter* adapter, + const DeviceDescriptor* descriptor); ~Device() override; MaybeError Initialize(); diff --git a/src/dawn_native/metal/BackendMTL.mm b/src/dawn_native/metal/BackendMTL.mm index 632aa8a07a..8b0194b913 100644 --- a/src/dawn_native/metal/BackendMTL.mm +++ b/src/dawn_native/metal/BackendMTL.mm @@ -277,8 +277,8 @@ namespace dawn_native { namespace metal { } private: - ResultOrError CreateDeviceImpl( - const DawnDeviceDescriptor* descriptor) override { + ResultOrError> CreateDeviceImpl( + const DeviceDescriptor* descriptor) override { return Device::Create(this, mDevice, descriptor); } diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h index 6f5153bc87..14c179fdf5 100644 --- a/src/dawn_native/metal/DeviceMTL.h +++ b/src/dawn_native/metal/DeviceMTL.h @@ -38,9 +38,9 @@ namespace dawn_native { namespace metal { class Device final : public DeviceBase { public: - static ResultOrError Create(AdapterBase* adapter, - NSPRef> mtlDevice, - const DawnDeviceDescriptor* descriptor); + static ResultOrError> Create(AdapterBase* adapter, + NSPRef> mtlDevice, + const DeviceDescriptor* descriptor); ~Device() override; MaybeError Initialize(); @@ -77,7 +77,7 @@ namespace dawn_native { namespace metal { private: Device(AdapterBase* adapter, NSPRef> mtlDevice, - const DawnDeviceDescriptor* descriptor); + const DeviceDescriptor* descriptor); ResultOrError> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm index c79cff412c..f02d096fae 100644 --- a/src/dawn_native/metal/DeviceMTL.mm +++ b/src/dawn_native/metal/DeviceMTL.mm @@ -106,17 +106,17 @@ namespace dawn_native { namespace metal { } // namespace // static - ResultOrError Device::Create(AdapterBase* adapter, - NSPRef> mtlDevice, - const DawnDeviceDescriptor* descriptor) { + ResultOrError> Device::Create(AdapterBase* adapter, + NSPRef> mtlDevice, + const DeviceDescriptor* descriptor) { Ref device = AcquireRef(new Device(adapter, std::move(mtlDevice), descriptor)); DAWN_TRY(device->Initialize()); - return device.Detach(); + return device; } Device::Device(AdapterBase* adapter, NSPRef> mtlDevice, - const DawnDeviceDescriptor* descriptor) + const DeviceDescriptor* descriptor) : DeviceBase(adapter, descriptor), mMtlDevice(std::move(mtlDevice)), mCompletedSerial(0) { } diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp index b7146b9147..58a783c582 100644 --- a/src/dawn_native/null/DeviceNull.cpp +++ b/src/dawn_native/null/DeviceNull.cpp @@ -38,8 +38,11 @@ namespace dawn_native { namespace null { } // Used for the tests that intend to use an adapter without all features enabled. - void Adapter::SetSupportedFeatures(const std::vector& requiredFeatures) { - mSupportedFeatures = GetInstance()->FeatureNamesToFeaturesSet(requiredFeatures); + void Adapter::SetSupportedFeatures(const std::vector& requiredFeatures) { + mSupportedFeatures = {}; + for (wgpu::FeatureName f : requiredFeatures) { + mSupportedFeatures.EnableFeature(f); + } } MaybeError Adapter::InitializeImpl() { @@ -57,7 +60,7 @@ namespace dawn_native { namespace null { return {}; } - ResultOrError Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) { + ResultOrError> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { return Device::Create(this, descriptor); } @@ -95,11 +98,11 @@ namespace dawn_native { namespace null { // Device // static - ResultOrError Device::Create(Adapter* adapter, - const DawnDeviceDescriptor* descriptor) { + ResultOrError> Device::Create(Adapter* adapter, + const DeviceDescriptor* descriptor) { Ref device = AcquireRef(new Device(adapter, descriptor)); DAWN_TRY(device->Initialize()); - return device.Detach(); + return device; } Device::~Device() { diff --git a/src/dawn_native/null/DeviceNull.h b/src/dawn_native/null/DeviceNull.h index 380295bba7..ef2adfbeaf 100644 --- a/src/dawn_native/null/DeviceNull.h +++ b/src/dawn_native/null/DeviceNull.h @@ -86,8 +86,8 @@ namespace dawn_native { namespace null { class Device final : public DeviceBase { public: - static ResultOrError Create(Adapter* adapter, - const DawnDeviceDescriptor* descriptor); + static ResultOrError> Create(Adapter* adapter, + const DeviceDescriptor* descriptor); ~Device() override; MaybeError Initialize(); @@ -175,15 +175,15 @@ namespace dawn_native { namespace null { bool SupportsExternalImages() const override; // Used for the tests that intend to use an adapter without all features enabled. - void SetSupportedFeatures(const std::vector& requiredFeatures); + void SetSupportedFeatures(const std::vector& requiredFeatures); private: MaybeError InitializeImpl() override; MaybeError InitializeSupportedFeaturesImpl() override; MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override; - ResultOrError CreateDeviceImpl( - const DawnDeviceDescriptor* descriptor) override; + ResultOrError> CreateDeviceImpl( + const DeviceDescriptor* descriptor) override; }; // Helper class so |BindGroup| can allocate memory for its binding data, diff --git a/src/dawn_native/opengl/BackendGL.cpp b/src/dawn_native/opengl/BackendGL.cpp index 3c57200b59..611d258d6a 100644 --- a/src/dawn_native/opengl/BackendGL.cpp +++ b/src/dawn_native/opengl/BackendGL.cpp @@ -254,8 +254,8 @@ namespace dawn_native { namespace opengl { return {}; } - ResultOrError CreateDeviceImpl( - const DawnDeviceDescriptor* descriptor) override { + ResultOrError> CreateDeviceImpl( + const DeviceDescriptor* descriptor) override { // There is no limit on the number of devices created from this adapter because they can // all share the same backing OpenGL context. return Device::Create(this, descriptor, mFunctions); diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp index 89bd9f8a11..0240e06750 100644 --- a/src/dawn_native/opengl/DeviceGL.cpp +++ b/src/dawn_native/opengl/DeviceGL.cpp @@ -35,16 +35,16 @@ namespace dawn_native { namespace opengl { // static - ResultOrError Device::Create(AdapterBase* adapter, - const DawnDeviceDescriptor* descriptor, - const OpenGLFunctions& functions) { + ResultOrError> Device::Create(AdapterBase* adapter, + const DeviceDescriptor* descriptor, + const OpenGLFunctions& functions) { Ref device = AcquireRef(new Device(adapter, descriptor, functions)); DAWN_TRY(device->Initialize()); - return device.Detach(); + return device; } Device::Device(AdapterBase* adapter, - const DawnDeviceDescriptor* descriptor, + const DeviceDescriptor* descriptor, const OpenGLFunctions& functions) : DeviceBase(adapter, descriptor), gl(functions) { } diff --git a/src/dawn_native/opengl/DeviceGL.h b/src/dawn_native/opengl/DeviceGL.h index f1317069b1..1bd8f31d57 100644 --- a/src/dawn_native/opengl/DeviceGL.h +++ b/src/dawn_native/opengl/DeviceGL.h @@ -37,9 +37,9 @@ namespace dawn_native { namespace opengl { class Device final : public DeviceBase { public: - static ResultOrError Create(AdapterBase* adapter, - const DawnDeviceDescriptor* descriptor, - const OpenGLFunctions& functions); + static ResultOrError> Create(AdapterBase* adapter, + const DeviceDescriptor* descriptor, + const OpenGLFunctions& functions); ~Device() override; MaybeError Initialize(); @@ -81,7 +81,7 @@ namespace dawn_native { namespace opengl { private: Device(AdapterBase* adapter, - const DawnDeviceDescriptor* descriptor, + const DeviceDescriptor* descriptor, const OpenGLFunctions& functions); ResultOrError> CreateBindGroupImpl( diff --git a/src/dawn_native/vulkan/AdapterVk.cpp b/src/dawn_native/vulkan/AdapterVk.cpp index 816efff76a..4f8b1c95ec 100644 --- a/src/dawn_native/vulkan/AdapterVk.cpp +++ b/src/dawn_native/vulkan/AdapterVk.cpp @@ -338,7 +338,7 @@ namespace dawn_native { namespace vulkan { mVulkanInstance->GetFunctions()); } - ResultOrError Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) { + ResultOrError> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { return Device::Create(this, descriptor); } diff --git a/src/dawn_native/vulkan/AdapterVk.h b/src/dawn_native/vulkan/AdapterVk.h index 7e9257cbf5..6d93a07fea 100644 --- a/src/dawn_native/vulkan/AdapterVk.h +++ b/src/dawn_native/vulkan/AdapterVk.h @@ -46,8 +46,8 @@ namespace dawn_native { namespace vulkan { MaybeError InitializeSupportedFeaturesImpl() override; MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override; - ResultOrError CreateDeviceImpl( - const DawnDeviceDescriptor* descriptor) override; + ResultOrError> CreateDeviceImpl( + const DeviceDescriptor* descriptor) override; VkPhysicalDevice mPhysicalDevice; Ref mVulkanInstance; diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp index de7c8d422a..2c2c48b39a 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -45,14 +45,14 @@ namespace dawn_native { namespace vulkan { // static - ResultOrError Device::Create(Adapter* adapter, - const DawnDeviceDescriptor* descriptor) { + ResultOrError> Device::Create(Adapter* adapter, + const DeviceDescriptor* descriptor) { Ref device = AcquireRef(new Device(adapter, descriptor)); DAWN_TRY(device->Initialize()); - return device.Detach(); + return device; } - Device::Device(Adapter* adapter, const DawnDeviceDescriptor* descriptor) + Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor) : DeviceBase(adapter, descriptor) { InitTogglesFromDriver(); } diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h index 1c697a84aa..00f32c727f 100644 --- a/src/dawn_native/vulkan/DeviceVk.h +++ b/src/dawn_native/vulkan/DeviceVk.h @@ -43,8 +43,8 @@ namespace dawn_native { namespace vulkan { class Device final : public DeviceBase { public: - static ResultOrError Create(Adapter* adapter, - const DawnDeviceDescriptor* descriptor); + static ResultOrError> Create(Adapter* adapter, + const DeviceDescriptor* descriptor); ~Device() override; MaybeError Initialize(); @@ -106,7 +106,7 @@ namespace dawn_native { namespace vulkan { float GetTimestampPeriodInNS() const override; private: - Device(Adapter* adapter, const DawnDeviceDescriptor* descriptor); + Device(Adapter* adapter, const DeviceDescriptor* descriptor); ResultOrError> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; diff --git a/src/dawn_wire/SupportedFeatures.cpp b/src/dawn_wire/SupportedFeatures.cpp index a1d4006b97..41c3a4ad80 100644 --- a/src/dawn_wire/SupportedFeatures.cpp +++ b/src/dawn_wire/SupportedFeatures.cpp @@ -22,6 +22,7 @@ namespace dawn_wire { switch (feature) { case WGPUFeatureName_Undefined: case WGPUFeatureName_Force32: + case WGPUFeatureName_DawnNative: return false; case WGPUFeatureName_Depth24UnormStencil8: case WGPUFeatureName_Depth32FloatStencil8: diff --git a/src/dawn_wire/client/Adapter.cpp b/src/dawn_wire/client/Adapter.cpp index fd5daf7da6..db9986ffa6 100644 --- a/src/dawn_wire/client/Adapter.cpp +++ b/src/dawn_wire/client/Adapter.cpp @@ -14,6 +14,7 @@ #include "dawn_wire/client/Adapter.h" +#include "common/Log.h" #include "dawn_wire/client/Client.h" namespace dawn_wire { namespace client { @@ -124,4 +125,9 @@ namespace dawn_wire { namespace client { return true; } + WGPUDevice Adapter::CreateDevice(const WGPUDeviceDescriptor*) { + dawn::ErrorLog() << "adapter.CreateDevice not supported with dawn_wire."; + return nullptr; + } + }} // namespace dawn_wire::client diff --git a/src/dawn_wire/client/Adapter.h b/src/dawn_wire/client/Adapter.h index e6f77dc75b..26c8222d55 100644 --- a/src/dawn_wire/client/Adapter.h +++ b/src/dawn_wire/client/Adapter.h @@ -50,6 +50,9 @@ namespace dawn_wire { namespace client { uint32_t featuresCount, const WGPUFeatureName* features); + // Unimplementable. Only availale in dawn_native. + WGPUDevice CreateDevice(const WGPUDeviceDescriptor*); + private: LimitsAndFeatures mLimitsAndFeatures; WGPUAdapterProperties mProperties; diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h index a73f4f2f6b..fb2bd7861c 100644 --- a/src/include/dawn_native/DawnNative.h +++ b/src/include/dawn_native/DawnNative.h @@ -121,15 +121,17 @@ namespace dawn_native { explicit operator bool() const; - // Create a device on this adapter, note that the interface will change to include at least - // a device descriptor and a pointer to backend specific options. - // On an error, nullptr is returned. - WGPUDevice CreateDevice(const DawnDeviceDescriptor* deviceDescriptor = nullptr); + // Create a device on this adapter. On an error, nullptr is returned. + WGPUDevice CreateDevice(const DawnDeviceDescriptor* deviceDescriptor); + WGPUDevice CreateDevice(const WGPUDeviceDescriptor* deviceDescriptor = nullptr); void RequestDevice(const DawnDeviceDescriptor* descriptor, WGPURequestDeviceCallback callback, void* userdata); + // Returns the underlying WGPUAdapter object. + WGPUAdapter Get() const; + // Reset the backend device object for testing purposes. void ResetInternalDeviceForTesting(); @@ -173,6 +175,7 @@ namespace dawn_native { std::vector GetAdapters() const; const ToggleInfo* GetToggleInfo(const char* toggleName); + const FeatureInfo* GetFeatureInfo(WGPUFeatureName feature); // Enables backend validation layers void EnableBackendValidation(bool enableBackendValidation); diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn index 4eb64a3cfc..6141875c5f 100644 --- a/src/tests/BUILD.gn +++ b/src/tests/BUILD.gn @@ -227,6 +227,7 @@ test("dawn_unittests") { "unittests/TypedIntegerTests.cpp", "unittests/native/CommandBufferEncodingTests.cpp", "unittests/native/DestroyObjectTests.cpp", + "unittests/native/DeviceCreationTests.cpp", "unittests/validation/BindGroupValidationTests.cpp", "unittests/validation/BufferValidationTests.cpp", "unittests/validation/CommandBufferValidationTests.cpp", diff --git a/src/tests/unittests/FeatureTests.cpp b/src/tests/unittests/FeatureTests.cpp index 729dca6d2e..4e1e7970dc 100644 --- a/src/tests/unittests/FeatureTests.cpp +++ b/src/tests/unittests/FeatureTests.cpp @@ -26,10 +26,10 @@ class FeatureTests : public testing::Test { mAdapterBase(mInstanceBase.Get()) { } - std::vector GetAllFeatureNames() { - std::vector allFeatureNames(kTotalFeaturesCount); + std::vector GetAllFeatureNames() { + std::vector allFeatureNames(kTotalFeaturesCount); for (size_t i = 0; i < kTotalFeaturesCount; ++i) { - allFeatureNames[i] = FeatureEnumToName(static_cast(i)); + allFeatureNames[i] = FeatureEnumToAPIFeature(static_cast(i)); } return allFeatureNames; } @@ -45,20 +45,23 @@ class FeatureTests : public testing::Test { // Test the creation of a device will fail if the requested feature is not supported on the // Adapter. TEST_F(FeatureTests, AdapterWithRequiredFeatureDisabled) { - const std::vector kAllFeatureNames = GetAllFeatureNames(); + const std::vector kAllFeatureNames = GetAllFeatureNames(); for (size_t i = 0; i < kTotalFeaturesCount; ++i) { dawn_native::Feature notSupportedFeature = static_cast(i); - std::vector featureNamesWithoutOne = kAllFeatureNames; + std::vector featureNamesWithoutOne = kAllFeatureNames; featureNamesWithoutOne.erase(featureNamesWithoutOne.begin() + i); mAdapterBase.SetSupportedFeatures(featureNamesWithoutOne); dawn_native::Adapter adapterWithoutFeature(&mAdapterBase); - dawn_native::DawnDeviceDescriptor deviceDescriptor; - const char* featureName = FeatureEnumToName(notSupportedFeature); - deviceDescriptor.requiredFeatures = std::vector(1, featureName); - WGPUDevice deviceWithFeature = adapterWithoutFeature.CreateDevice(&deviceDescriptor); + wgpu::DeviceDescriptor deviceDescriptor; + wgpu::FeatureName featureName = FeatureEnumToAPIFeature(notSupportedFeature); + deviceDescriptor.requiredFeatures = &featureName; + deviceDescriptor.requiredFeaturesCount = 1; + + WGPUDevice deviceWithFeature = adapterWithoutFeature.CreateDevice( + reinterpret_cast(&deviceDescriptor)); ASSERT_EQ(nullptr, deviceWithFeature); } } @@ -68,14 +71,18 @@ TEST_F(FeatureTests, GetEnabledFeatures) { dawn_native::Adapter adapter(&mAdapterBase); for (size_t i = 0; i < kTotalFeaturesCount; ++i) { dawn_native::Feature feature = static_cast(i); - const char* featureName = FeatureEnumToName(feature); + wgpu::FeatureName featureName = FeatureEnumToAPIFeature(feature); - dawn_native::DawnDeviceDescriptor deviceDescriptor; - deviceDescriptor.requiredFeatures = {featureName}; - dawn_native::DeviceBase* deviceBase = - dawn_native::FromAPI(adapter.CreateDevice(&deviceDescriptor)); - std::vector enabledFeatures = deviceBase->GetEnabledFeatures(); - ASSERT_EQ(1u, enabledFeatures.size()); - ASSERT_EQ(0, std::strcmp(featureName, enabledFeatures[0])); + wgpu::DeviceDescriptor deviceDescriptor; + deviceDescriptor.requiredFeatures = &featureName; + deviceDescriptor.requiredFeaturesCount = 1; + + dawn_native::DeviceBase* deviceBase = dawn_native::FromAPI( + adapter.CreateDevice(reinterpret_cast(&deviceDescriptor))); + + ASSERT_EQ(1u, deviceBase->APIEnumerateFeatures(nullptr)); + wgpu::FeatureName enabledFeature; + deviceBase->APIEnumerateFeatures(&enabledFeature); + EXPECT_EQ(enabledFeature, featureName); } } diff --git a/src/tests/unittests/GetProcAddressTests.cpp b/src/tests/unittests/GetProcAddressTests.cpp index 8f90efcbf3..e2c6afd0ae 100644 --- a/src/tests/unittests/GetProcAddressTests.cpp +++ b/src/tests/unittests/GetProcAddressTests.cpp @@ -59,7 +59,7 @@ namespace { switch (GetParam()) { case DawnFlavor::Native: { mDevice = wgpu::Device::Acquire( - reinterpret_cast(mNativeAdapter.CreateDevice(nullptr))); + reinterpret_cast(mNativeAdapter.APICreateDevice())); mProcs = dawn_native::GetProcs(); break; } diff --git a/src/tests/unittests/PerThreadProcTests.cpp b/src/tests/unittests/PerThreadProcTests.cpp index 38ce981eab..6151a6c8aa 100644 --- a/src/tests/unittests/PerThreadProcTests.cpp +++ b/src/tests/unittests/PerThreadProcTests.cpp @@ -57,10 +57,10 @@ TEST_F(PerThreadProcTests, DispatchesPerThread) { // Note: Acquire doesn't call reference or release. wgpu::Device deviceA = - wgpu::Device::Acquire(reinterpret_cast(mNativeAdapter.CreateDevice(nullptr))); + wgpu::Device::Acquire(reinterpret_cast(mNativeAdapter.APICreateDevice())); wgpu::Device deviceB = - wgpu::Device::Acquire(reinterpret_cast(mNativeAdapter.CreateDevice(nullptr))); + wgpu::Device::Acquire(reinterpret_cast(mNativeAdapter.APICreateDevice())); std::thread threadA([&]() { DawnProcTable procs = dawn_native::GetProcs(); diff --git a/src/tests/unittests/native/DeviceCreationTests.cpp b/src/tests/unittests/native/DeviceCreationTests.cpp new file mode 100644 index 0000000000..64022861dd --- /dev/null +++ b/src/tests/unittests/native/DeviceCreationTests.cpp @@ -0,0 +1,115 @@ +// Copyright 2021 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/dawn_proc.h" +#include "dawn_native/DawnNative.h" +#include "tests/MockCallback.h" +#include "utils/SystemUtils.h" +#include "utils/WGPUHelpers.h" + +#include + +namespace { + + using namespace testing; + + class DeviceCreationTest : public testing::Test { + protected: + void SetUp() override { + dawnProcSetProcs(&dawn_native::GetProcs()); + + instance = std::make_unique(); + instance->DiscoverDefaultAdapters(); + for (dawn_native::Adapter& nativeAdapter : instance->GetAdapters()) { + wgpu::AdapterProperties properties; + nativeAdapter.GetProperties(&properties); + + if (properties.backendType == wgpu::BackendType::Null) { + adapter = wgpu::Adapter(nativeAdapter.Get()); + break; + } + } + ASSERT_NE(adapter, nullptr); + } + + void TearDown() override { + adapter = nullptr; + instance = nullptr; + dawnProcSetProcs(nullptr); + } + + std::unique_ptr instance; + wgpu::Adapter adapter; + }; + + // Test successful call to CreateDevice with no descriptor + TEST_F(DeviceCreationTest, CreateDeviceNoDescriptorSuccess) { + wgpu::Device device = adapter.CreateDevice(); + EXPECT_NE(device, nullptr); + } + + // Test successful call to CreateDevice with descriptor. + TEST_F(DeviceCreationTest, CreateDeviceSuccess) { + wgpu::DeviceDescriptor desc = {}; + wgpu::Device device = adapter.CreateDevice(&desc); + EXPECT_NE(device, nullptr); + } + + // Test successful call to CreateDevice with toggle descriptor. + TEST_F(DeviceCreationTest, CreateDeviceWithTogglesSuccess) { + wgpu::DeviceDescriptor desc = {}; + wgpu::DawnTogglesDeviceDescriptor togglesDesc = {}; + desc.nextInChain = &togglesDesc; + + const char* toggle = "skip_validation"; + togglesDesc.forceEnabledToggles = &toggle; + togglesDesc.forceEnabledTogglesCount = 1; + + wgpu::Device device = adapter.CreateDevice(&desc); + EXPECT_NE(device, nullptr); + + auto toggles = dawn_native::GetTogglesUsed(device.Get()); + EXPECT_THAT(toggles, testing::Contains(testing::StrEq(toggle))); + } + + // Test successful call to RequestDevice with descriptor + TEST_F(DeviceCreationTest, RequestDeviceSuccess) { + WGPUDevice cDevice; + { + MockCallback cb; + EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Success, NotNull(), nullptr, this)) + .WillOnce(SaveArg<1>(&cDevice)); + + wgpu::DeviceDescriptor desc = {}; + adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this)); + } + + wgpu::Device device = wgpu::Device::Acquire(cDevice); + EXPECT_NE(device, nullptr); + } + + // Test failing call to RequestDevice with invalid feature + TEST_F(DeviceCreationTest, RequestDeviceFailure) { + MockCallback cb; + EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Error, nullptr, NotNull(), this)).Times(1); + + wgpu::DeviceDescriptor desc = {}; + wgpu::FeatureName invalidFeature = static_cast(WGPUFeatureName_Force32); + desc.requiredFeatures = &invalidFeature; + desc.requiredFeaturesCount = 1; + + adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this)); + } + +} // anonymous namespace diff --git a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp index f1f3c27f0b..830d5fde3f 100644 --- a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp +++ b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp @@ -312,17 +312,21 @@ namespace dawn_native { namespace vulkan { // Create another device based on the original backendAdapter = dawn_native::vulkan::ToBackend(deviceVk->GetAdapter()); - deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds; - deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds; + deviceDescriptor.nextInChain = &togglesDesc; + togglesDesc.forceEnabledToggles = GetParam().forceEnabledWorkarounds.data(); + togglesDesc.forceEnabledTogglesCount = GetParam().forceEnabledWorkarounds.size(); + togglesDesc.forceDisabledToggles = GetParam().forceDisabledWorkarounds.data(); + togglesDesc.forceDisabledTogglesCount = GetParam().forceDisabledWorkarounds.size(); secondDeviceVk = - dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor)); + dawn_native::vulkan::ToBackend(backendAdapter->APICreateDevice(&deviceDescriptor)); secondDevice = wgpu::Device::Acquire(dawn_native::ToAPI(secondDeviceVk)); } protected: dawn_native::vulkan::Adapter* backendAdapter; - dawn_native::DawnDeviceDescriptor deviceDescriptor; + dawn_native::DeviceDescriptor deviceDescriptor; + dawn_native::DawnTogglesDeviceDescriptor togglesDesc; wgpu::Device secondDevice; dawn_native::vulkan::Device* secondDeviceVk; @@ -691,7 +695,7 @@ namespace dawn_native { namespace vulkan { // device 2 = |secondDevice| // Create device 3 dawn_native::vulkan::Device* thirdDeviceVk = - dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor)); + dawn_native::vulkan::ToBackend(backendAdapter->APICreateDevice(&deviceDescriptor)); wgpu::Device thirdDevice = wgpu::Device::Acquire(dawn_native::ToAPI(thirdDeviceVk)); // Make queue for device 2 and 3 diff --git a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp index 196c1b05ae..74c551a9b6 100644 --- a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp +++ b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp @@ -383,11 +383,14 @@ namespace dawn_native { namespace vulkan { // Create another device based on the original backendAdapter = dawn_native::vulkan::ToBackend(deviceVk->GetAdapter()); - deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds; - deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds; + deviceDescriptor.nextInChain = &togglesDesc; + togglesDesc.forceEnabledToggles = GetParam().forceEnabledWorkarounds.data(); + togglesDesc.forceEnabledTogglesCount = GetParam().forceEnabledWorkarounds.size(); + togglesDesc.forceDisabledToggles = GetParam().forceDisabledWorkarounds.data(); + togglesDesc.forceDisabledTogglesCount = GetParam().forceDisabledWorkarounds.size(); secondDeviceVk = - dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor)); + dawn_native::vulkan::ToBackend(backendAdapter->APICreateDevice(&deviceDescriptor)); secondDevice = wgpu::Device::Acquire(dawn_native::ToAPI(secondDeviceVk)); CreateBindExportImage(deviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &defaultImage, @@ -418,7 +421,8 @@ namespace dawn_native { namespace vulkan { dawn_native::vulkan::Device* secondDeviceVk; dawn_native::vulkan::Adapter* backendAdapter; - dawn_native::DawnDeviceDescriptor deviceDescriptor; + dawn_native::DeviceDescriptor deviceDescriptor; + dawn_native::DawnTogglesDeviceDescriptor togglesDesc; wgpu::TextureDescriptor defaultDescriptor; VkImage defaultImage; @@ -797,7 +801,7 @@ namespace dawn_native { namespace vulkan { // device 2 = |secondDevice| // Create device 3 dawn_native::vulkan::Device* thirdDeviceVk = - dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor)); + dawn_native::vulkan::ToBackend(backendAdapter->APICreateDevice(&deviceDescriptor)); wgpu::Device thirdDevice = wgpu::Device::Acquire(dawn_native::ToAPI(thirdDeviceVk)); // Make queue for device 2 and 3