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 <lokokung@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2021-12-22 19:02:23 +00:00 committed by Dawn LUCI CQ
parent 59c84575f7
commit 2f218e2b21
41 changed files with 472 additions and 223 deletions

View File

@ -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": {

View File

@ -179,6 +179,7 @@
"SurfaceDescriptorFromWindowsSwapChainPanel"
],
"client_side_commands": [
"AdapterCreateDevice",
"AdapterGetProperties",
"AdapterGetLimits",
"AdapterHasFeature",

View File

@ -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.

View File

@ -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),

View File

@ -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 %}

View File

@ -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> errorData = result.AcquireError();
callback(WGPURequestDeviceStatus_Error, nullptr,
errorData->GetFormattedMessage().c_str(), userdata);
return;
}
Ref<DeviceBase> 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<const char*>& 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<size_t, const wgpu::FeatureName>& 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<Ref<DeviceBase>> 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> 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) {

View File

@ -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<const char*>& requestedFeatures) const;
bool SupportsAllRequiredFeatures(
const ityp::span<size_t, const wgpu::FeatureName>& features) const;
WGPUDeviceProperties GetAdapterProperties() const;
bool GetLimits(SupportedLimits* limits) const;
@ -76,8 +73,8 @@ namespace dawn_native {
FeaturesSet mSupportedFeatures;
private:
virtual ResultOrError<DeviceBase*> CreateDeviceImpl(
const DawnDeviceDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<DeviceBase>> 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<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor);
virtual MaybeError ResetInternalDeviceForTestingImpl();
InstanceBase* mInstance = nullptr;

View File

@ -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<const RequiredLimits*>(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<wgpu::FeatureName> 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<const char*> 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<wgpu::FeatureName>(feature));
}
void Instance::EnableBackendValidation(bool enableBackendValidation) {
if (enableBackendValidation) {
mImpl->SetBackendValidationLevel(BackendValidationLevel::Full);

View File

@ -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<const char*> 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);

View File

@ -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<const char*> GetEnabledFeatures() const;
std::vector<const char*> 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();

View File

@ -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<size_t>(feature);
@ -184,8 +197,13 @@ namespace dawn_native {
uint32_t index = 0;
for (uint32_t i : IterateBitSet(featuresBitSet)) {
const char* featureName = FeatureEnumToName(static_cast<Feature>(i));
enabledFeatureNames[index] = featureName;
Feature feature = static_cast<Feature>(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<size_t>(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<size_t>(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<size_t>(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<const char*>& 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<wgpu::FeatureName>(-1);
}
} // namespace dawn_native

View File

@ -39,6 +39,7 @@ namespace dawn_native {
// Dawn-specific
DawnInternalUsages,
MultiPlanarFormats,
DawnNative,
EnumCount,
InvalidEnum = EnumCount,
@ -51,6 +52,7 @@ namespace dawn_native {
std::bitset<static_cast<size_t>(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<const char*>& requiredFeatures) const;
wgpu::FeatureName FeatureNameToAPIEnum(const char* featureName) const;
private:
std::unordered_map<std::string, Feature> mFeatureNameToEnumMap;

View File

@ -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<const char*>& requiredFeatures) {
return mFeaturesInfo.FeatureNamesToFeaturesSet(requiredFeatures);
const FeatureInfo* InstanceBase::GetFeatureInfo(wgpu::FeatureName feature) {
return mFeaturesInfo.GetFeatureInfo(feature);
}
const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {

View File

@ -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<const char*>& requiredFeatures);
const FeatureInfo* GetFeatureInfo(wgpu::FeatureName feature);
bool IsBackendValidationEnabled() const;
void SetBackendValidationLevel(BackendValidationLevel level);

View File

@ -394,7 +394,7 @@ namespace dawn_native { namespace d3d12 {
infoQueue->PopStorageFilter();
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
return Device::Create(this, descriptor);
}

View File

@ -40,8 +40,8 @@ namespace dawn_native { namespace d3d12 {
const gpu_info::D3DDriverVersion& GetDriverVersion() const;
private:
ResultOrError<DeviceBase*> CreateDeviceImpl(
const DawnDeviceDescriptor* descriptor) override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor) override;
MaybeError ResetInternalDeviceForTestingImpl() override;
bool AreTimestampQueriesSupported() const;

View File

@ -56,11 +56,11 @@ namespace dawn_native { namespace d3d12 {
static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
// static
ResultOrError<Device*> Device::Create(Adapter* adapter,
const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
const DeviceDescriptor* descriptor) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor));
DAWN_TRY(device->Initialize());
return device.Detach();
return device;
}
MaybeError Device::Initialize() {

View File

@ -41,8 +41,8 @@ namespace dawn_native { namespace d3d12 {
// Definition of backend types
class Device final : public DeviceBase {
public:
static ResultOrError<Device*> Create(Adapter* adapter,
const DawnDeviceDescriptor* descriptor);
static ResultOrError<Ref<Device>> Create(Adapter* adapter,
const DeviceDescriptor* descriptor);
~Device() override;
MaybeError Initialize();

View File

@ -277,8 +277,8 @@ namespace dawn_native { namespace metal {
}
private:
ResultOrError<DeviceBase*> CreateDeviceImpl(
const DawnDeviceDescriptor* descriptor) override {
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor) override {
return Device::Create(this, mDevice, descriptor);
}

View File

@ -38,9 +38,9 @@ namespace dawn_native { namespace metal {
class Device final : public DeviceBase {
public:
static ResultOrError<Device*> Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DawnDeviceDescriptor* descriptor);
static ResultOrError<Ref<Device>> Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DeviceDescriptor* descriptor);
~Device() override;
MaybeError Initialize();
@ -77,7 +77,7 @@ namespace dawn_native { namespace metal {
private:
Device(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DawnDeviceDescriptor* descriptor);
const DeviceDescriptor* descriptor);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;

View File

@ -106,17 +106,17 @@ namespace dawn_native { namespace metal {
} // namespace
// static
ResultOrError<Device*> Device::Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DeviceDescriptor* descriptor) {
Ref<Device> device = AcquireRef(new Device(adapter, std::move(mtlDevice), descriptor));
DAWN_TRY(device->Initialize());
return device.Detach();
return device;
}
Device::Device(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DawnDeviceDescriptor* descriptor)
const DeviceDescriptor* descriptor)
: DeviceBase(adapter, descriptor), mMtlDevice(std::move(mtlDevice)), mCompletedSerial(0) {
}

View File

@ -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<const char*>& requiredFeatures) {
mSupportedFeatures = GetInstance()->FeatureNamesToFeaturesSet(requiredFeatures);
void Adapter::SetSupportedFeatures(const std::vector<wgpu::FeatureName>& requiredFeatures) {
mSupportedFeatures = {};
for (wgpu::FeatureName f : requiredFeatures) {
mSupportedFeatures.EnableFeature(f);
}
}
MaybeError Adapter::InitializeImpl() {
@ -57,7 +60,7 @@ namespace dawn_native { namespace null {
return {};
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
return Device::Create(this, descriptor);
}
@ -95,11 +98,11 @@ namespace dawn_native { namespace null {
// Device
// static
ResultOrError<Device*> Device::Create(Adapter* adapter,
const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
const DeviceDescriptor* descriptor) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor));
DAWN_TRY(device->Initialize());
return device.Detach();
return device;
}
Device::~Device() {

View File

@ -86,8 +86,8 @@ namespace dawn_native { namespace null {
class Device final : public DeviceBase {
public:
static ResultOrError<Device*> Create(Adapter* adapter,
const DawnDeviceDescriptor* descriptor);
static ResultOrError<Ref<Device>> 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<const char*>& requiredFeatures);
void SetSupportedFeatures(const std::vector<wgpu::FeatureName>& requiredFeatures);
private:
MaybeError InitializeImpl() override;
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
ResultOrError<DeviceBase*> CreateDeviceImpl(
const DawnDeviceDescriptor* descriptor) override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor) override;
};
// Helper class so |BindGroup| can allocate memory for its binding data,

View File

@ -254,8 +254,8 @@ namespace dawn_native { namespace opengl {
return {};
}
ResultOrError<DeviceBase*> CreateDeviceImpl(
const DawnDeviceDescriptor* descriptor) override {
ResultOrError<Ref<DeviceBase>> 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);

View File

@ -35,16 +35,16 @@
namespace dawn_native { namespace opengl {
// static
ResultOrError<Device*> Device::Create(AdapterBase* adapter,
const DawnDeviceDescriptor* descriptor,
const OpenGLFunctions& functions) {
ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions) {
Ref<Device> 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) {
}

View File

@ -37,9 +37,9 @@ namespace dawn_native { namespace opengl {
class Device final : public DeviceBase {
public:
static ResultOrError<Device*> Create(AdapterBase* adapter,
const DawnDeviceDescriptor* descriptor,
const OpenGLFunctions& functions);
static ResultOrError<Ref<Device>> 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<Ref<BindGroupBase>> CreateBindGroupImpl(

View File

@ -338,7 +338,7 @@ namespace dawn_native { namespace vulkan {
mVulkanInstance->GetFunctions());
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
return Device::Create(this, descriptor);
}

View File

@ -46,8 +46,8 @@ namespace dawn_native { namespace vulkan {
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
ResultOrError<DeviceBase*> CreateDeviceImpl(
const DawnDeviceDescriptor* descriptor) override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor) override;
VkPhysicalDevice mPhysicalDevice;
Ref<VulkanInstance> mVulkanInstance;

View File

@ -45,14 +45,14 @@
namespace dawn_native { namespace vulkan {
// static
ResultOrError<Device*> Device::Create(Adapter* adapter,
const DawnDeviceDescriptor* descriptor) {
ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
const DeviceDescriptor* descriptor) {
Ref<Device> 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();
}

View File

@ -43,8 +43,8 @@ namespace dawn_native { namespace vulkan {
class Device final : public DeviceBase {
public:
static ResultOrError<Device*> Create(Adapter* adapter,
const DawnDeviceDescriptor* descriptor);
static ResultOrError<Ref<Device>> 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<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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<Adapter> GetAdapters() const;
const ToggleInfo* GetToggleInfo(const char* toggleName);
const FeatureInfo* GetFeatureInfo(WGPUFeatureName feature);
// Enables backend validation layers
void EnableBackendValidation(bool enableBackendValidation);

View File

@ -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",

View File

@ -26,10 +26,10 @@ class FeatureTests : public testing::Test {
mAdapterBase(mInstanceBase.Get()) {
}
std::vector<const char*> GetAllFeatureNames() {
std::vector<const char*> allFeatureNames(kTotalFeaturesCount);
std::vector<wgpu::FeatureName> GetAllFeatureNames() {
std::vector<wgpu::FeatureName> allFeatureNames(kTotalFeaturesCount);
for (size_t i = 0; i < kTotalFeaturesCount; ++i) {
allFeatureNames[i] = FeatureEnumToName(static_cast<dawn_native::Feature>(i));
allFeatureNames[i] = FeatureEnumToAPIFeature(static_cast<dawn_native::Feature>(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<const char*> kAllFeatureNames = GetAllFeatureNames();
const std::vector<wgpu::FeatureName> kAllFeatureNames = GetAllFeatureNames();
for (size_t i = 0; i < kTotalFeaturesCount; ++i) {
dawn_native::Feature notSupportedFeature = static_cast<dawn_native::Feature>(i);
std::vector<const char*> featureNamesWithoutOne = kAllFeatureNames;
std::vector<wgpu::FeatureName> 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<const char*>(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<const WGPUDeviceDescriptor*>(&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<dawn_native::Feature>(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<const char*> 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<const WGPUDeviceDescriptor*>(&deviceDescriptor)));
ASSERT_EQ(1u, deviceBase->APIEnumerateFeatures(nullptr));
wgpu::FeatureName enabledFeature;
deviceBase->APIEnumerateFeatures(&enabledFeature);
EXPECT_EQ(enabledFeature, featureName);
}
}

View File

@ -59,7 +59,7 @@ namespace {
switch (GetParam()) {
case DawnFlavor::Native: {
mDevice = wgpu::Device::Acquire(
reinterpret_cast<WGPUDevice>(mNativeAdapter.CreateDevice(nullptr)));
reinterpret_cast<WGPUDevice>(mNativeAdapter.APICreateDevice()));
mProcs = dawn_native::GetProcs();
break;
}

View File

@ -57,10 +57,10 @@ TEST_F(PerThreadProcTests, DispatchesPerThread) {
// Note: Acquire doesn't call reference or release.
wgpu::Device deviceA =
wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(mNativeAdapter.CreateDevice(nullptr)));
wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(mNativeAdapter.APICreateDevice()));
wgpu::Device deviceB =
wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(mNativeAdapter.CreateDevice(nullptr)));
wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(mNativeAdapter.APICreateDevice()));
std::thread threadA([&]() {
DawnProcTable procs = dawn_native::GetProcs();

View File

@ -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 <gtest/gtest.h>
namespace {
using namespace testing;
class DeviceCreationTest : public testing::Test {
protected:
void SetUp() override {
dawnProcSetProcs(&dawn_native::GetProcs());
instance = std::make_unique<dawn_native::Instance>();
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<dawn_native::Instance> 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<WGPURequestDeviceCallback> 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<WGPURequestDeviceCallback> cb;
EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Error, nullptr, NotNull(), this)).Times(1);
wgpu::DeviceDescriptor desc = {};
wgpu::FeatureName invalidFeature = static_cast<wgpu::FeatureName>(WGPUFeatureName_Force32);
desc.requiredFeatures = &invalidFeature;
desc.requiredFeaturesCount = 1;
adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this));
}
} // anonymous namespace

View File

@ -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

View File

@ -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