dawn: Refactor device creation and add shader-f16 feature
This CL modifies the way adapter creating devices, adds `shader-f16`
feature, and deprecates the `dawn-shader-float16` feature which is no
longer used.
Details:
1. Parse the toggles chained with device descriptor in
`adapter::CreateDeviceInternal`, which are then used to validate
features requirement within `CreateDeviceInternal` and passed to device
constructor as initializer.
2. When creating device, validate features requirement in
`CreateDeviceInternal` with toggles known, make sure to fail the device
creation if a required feature is not supported by adapter or is guarded
by certain toggles which were not enabled/disabled. Feature ShaderF16
and ChromiumExperimentalDp4a are validated in this way. Unittest is
added to check creating devices with toggles-guarded features required.
3. Add `shader-f16` feature, which allow `using f16;` in WGSL code.
End-to-end tests are added to test a trival f16 WGSL shader could be
used if and only if the device has `shader-f16` feature.
4. Deprecate the `dawn-shader-float16` feature, which will be completely
removed after cleaning up Blink code.
Bug: dawn:1510
Change-Id: I6cb2dcbe1ee584fdd6131c62df1ee850b881dbd2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/100802
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/dawn.json b/dawn.json
index c842e79..d168b05 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1384,6 +1384,7 @@
{"value": 6, "name": "texture compression ETC2"},
{"value": 7, "name": "texture compression ASTC"},
{"value": 8, "name": "indirect first instance"},
+ {"value": 9, "name": "shader f16"},
{"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"]},
diff --git a/include/dawn/native/DawnNative.h b/include/dawn/native/DawnNative.h
index 1d7bf42..b2ffa5c 100644
--- a/include/dawn/native/DawnNative.h
+++ b/include/dawn/native/DawnNative.h
@@ -61,7 +61,15 @@
// A struct to record the information of a feature. A feature is a GPU feature that is not
// required to be supported by all Dawn backends and can only be used when it is enabled on the
// creation of device.
-using FeatureInfo = ToggleInfo;
+struct FeatureInfo {
+ const char* name;
+ const char* description;
+ const char* url;
+ // The enum of feature state, could be stable or experimental. Using an experimental feature
+ // requires DisallowUnsafeAPIs toggle being disabled.
+ enum class FeatureState { Stable = 0, Experimental };
+ FeatureState featureState;
+};
// An adapter is an object that represent on possibility of creating devices in the system.
// Most of the time it will represent a combination of a physical GPU and an API. Not that the
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 7415312..0234e2c 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -19,6 +19,7 @@
#include "dawn/common/Constants.h"
#include "dawn/common/GPUInfo.h"
+#include "dawn/native/ChainUtils_autogen.h"
#include "dawn/native/Device.h"
#include "dawn/native/Instance.h"
#include "dawn/native/ValidationUtils_autogen.h"
@@ -189,15 +190,40 @@
return true;
}
+MaybeError AdapterBase::ValidateFeatureSupportedWithToggles(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ DAWN_TRY(ValidateFeatureName(feature));
+ DAWN_INVALID_IF(!mSupportedFeatures.IsEnabled(feature),
+ "Requested feature %s is not supported.", feature);
+
+ const FeatureInfo* featureInfo = GetInstance()->GetFeatureInfo(feature);
+ // Experimental features are guarded by toggle DisallowUnsafeAPIs.
+ if (featureInfo->featureState == FeatureInfo::FeatureState::Experimental) {
+ DAWN_INVALID_IF(!userProvidedToggles.IsDisabled(Toggle::DisallowUnsafeAPIs),
+ "Feature %s is guarded by toggle disallow_unsafe_apis.", featureInfo->name);
+ }
+
+ // Do backend-specific validation.
+ return ValidateFeatureSupportedWithTogglesImpl(feature, userProvidedToggles);
+}
+
ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
const DeviceDescriptor* descriptor) {
ASSERT(descriptor != nullptr);
+ // Check overriden toggles before creating device, as some device features may be guarded by
+ // toggles, and requiring such features without using corresponding toggles should fails the
+ // device creating.
+ const DawnTogglesDeviceDescriptor* togglesDesc = nullptr;
+ FindInChain(descriptor->nextInChain, &togglesDesc);
+ TripleStateTogglesSet userProvidedToggles =
+ TripleStateTogglesSet::CreateFromTogglesDeviceDescriptor(togglesDesc);
+
+ // Validate all required features are supported by the adapter and suitable under given toggles.
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);
+ wgpu::FeatureName feature = descriptor->requiredFeatures[i];
+ DAWN_TRY(ValidateFeatureSupportedWithToggles(feature, userProvidedToggles));
}
if (descriptor->requiredLimits != nullptr) {
@@ -208,7 +234,7 @@
DAWN_INVALID_IF(descriptor->requiredLimits->nextInChain != nullptr,
"nextInChain is not nullptr.");
}
- return CreateDeviceImpl(descriptor);
+ return CreateDeviceImpl(descriptor, userProvidedToggles);
}
void AdapterBase::SetUseTieredLimits(bool useTieredLimits) {
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index 6b6448f..8bef321 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -24,6 +24,7 @@
#include "dawn/native/Error.h"
#include "dawn/native/Features.h"
#include "dawn/native/Limits.h"
+#include "dawn/native/Toggles.h"
#include "dawn/native/dawn_platform.h"
namespace dawn::native {
@@ -72,14 +73,24 @@
std::string mName;
wgpu::AdapterType mAdapterType = wgpu::AdapterType::Unknown;
std::string mDriverDescription;
+
+ // Features set that CAN be supported by devices of this adapter. Some features in this set may
+ // be guarded by toggles, and creating a device with these features required may result in a
+ // validation error if proper toggles are not enabled/disabled.
FeaturesSet mSupportedFeatures;
+ // Check if a feature os supported by this adapter AND suitable with given toggles.
+ MaybeError ValidateFeatureSupportedWithToggles(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles);
private:
- virtual ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor) = 0;
+ virtual ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) = 0;
virtual MaybeError InitializeImpl() = 0;
- // Check base WebGPU features and discover supported featurees.
+ // Check base WebGPU features and discover supported features.
virtual MaybeError InitializeSupportedFeaturesImpl() = 0;
// Check base WebGPU limits and populate supported limits.
@@ -87,6 +98,10 @@
virtual void InitializeVendorArchitectureImpl();
+ virtual MaybeError ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) = 0;
+
ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor);
virtual MaybeError ResetInternalDeviceForTestingImpl();
diff --git a/src/dawn/native/CopyTextureForBrowserHelper.cpp b/src/dawn/native/CopyTextureForBrowserHelper.cpp
index d7890ed..6f89842 100644
--- a/src/dawn/native/CopyTextureForBrowserHelper.cpp
+++ b/src/dawn/native/CopyTextureForBrowserHelper.cpp
@@ -364,7 +364,7 @@
source->texture->GetSampleCount(), destination->texture->GetSampleCount());
DAWN_INVALID_IF(
- options->internalUsage && !device->IsFeatureEnabled(Feature::DawnInternalUsages),
+ options->internalUsage && !device->HasFeature(Feature::DawnInternalUsages),
"The internalUsage is true while the dawn-internal-usages feature is not enabled.");
UsageValidationMode mode =
options->internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 65e79c1..8112f64 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -170,20 +170,19 @@
// DeviceBase
-DeviceBase::DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor)
- : mAdapter(adapter), mNextPipelineCompatibilityToken(1) {
+DeviceBase::DeviceBase(AdapterBase* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles)
+ : mAdapter(adapter),
+ mEnabledToggles(userProvidedToggles.providedTogglesEnabled),
+ mOverridenToggles(userProvidedToggles.togglesIsProvided),
+ mNextPipelineCompatibilityToken(1) {
mAdapter->GetInstance()->IncrementDeviceCountForTesting();
ASSERT(descriptor != nullptr);
AdapterProperties adapterProperties;
adapter->APIGetProperties(&adapterProperties);
- const DawnTogglesDeviceDescriptor* togglesDesc = nullptr;
- FindInChain(descriptor->nextInChain, &togglesDesc);
- if (togglesDesc != nullptr) {
- ApplyToggleOverrides(togglesDesc);
- }
-
SetDefaultToggles();
ApplyFeatures(descriptor);
@@ -1323,17 +1322,19 @@
}
}
-bool DeviceBase::IsFeatureEnabled(Feature feature) const {
+bool DeviceBase::HasFeature(Feature feature) const {
return mEnabledFeatures.IsEnabled(feature);
}
void DeviceBase::SetWGSLExtensionAllowList() {
// Set the WGSL extensions allow list based on device's enabled features and other
- // propority. For example:
- // mWGSLExtensionAllowList.insert("InternalExtensionForTesting");
- if (IsFeatureEnabled(Feature::ChromiumExperimentalDp4a)) {
+ // propority.
+ if (mEnabledFeatures.IsEnabled(Feature::ChromiumExperimentalDp4a)) {
mWGSLExtensionAllowList.insert("chromium_experimental_dp4a");
}
+ if (mEnabledFeatures.IsEnabled(Feature::ShaderF16)) {
+ mWGSLExtensionAllowList.insert("f16");
+ }
}
WGSLExtensionSet DeviceBase::GetWGSLExtensionAllowList() const {
@@ -1800,27 +1801,6 @@
SetToggle(Toggle::DisallowUnsafeAPIs, true);
}
-void DeviceBase::ApplyToggleOverrides(const DawnTogglesDeviceDescriptor* togglesDescriptor) {
- ASSERT(togglesDescriptor != nullptr);
-
- 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 (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);
- }
- }
-}
-
void DeviceBase::FlushCallbackTaskQueue() {
if (!mCallbackTaskManager->IsEmpty()) {
// If a user calls Queue::Submit inside the callback, then the device will be ticked,
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index 42bc77b..4fbe874 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -62,7 +62,9 @@
class DeviceBase : public RefCountedWithExternalCount {
public:
- DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor);
+ DeviceBase(AdapterBase* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
~DeviceBase() override;
// Handles the error, causing a device loss if applicable. Almost always when a device loss
@@ -279,11 +281,7 @@
QueueBase* APIGetQueue();
bool APIGetLimits(SupportedLimits* limits) const;
- // Note that we should not use this function to query the features which can only be enabled
- // behind toggles (use IsFeatureEnabled() instead).
bool APIHasFeature(wgpu::FeatureName feature) const;
- // Note that we should not use this function to query the features which can only be enabled
- // behind toggles (use IsFeatureEnabled() instead).
size_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
void APIInjectError(wgpu::ErrorType type, const char* message);
bool APITick();
@@ -381,9 +379,7 @@
virtual bool ShouldDuplicateParametersForDrawIndirect(
const RenderPipelineBase* renderPipelineBase) const;
- // TODO(crbug.com/dawn/1434): Make this function non-overridable when we support requesting
- // Adapter with toggles.
- virtual bool IsFeatureEnabled(Feature feature) const;
+ bool HasFeature(Feature feature) const;
const CombinedLimits& GetLimits() const;
@@ -482,7 +478,6 @@
WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata);
- 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 d375b20..4589f1c 100644
--- a/src/dawn/native/Features.cpp
+++ b/src/dawn/native/Features.cpp
@@ -34,58 +34,64 @@
static constexpr FeatureEnumAndInfoList kFeatureNameAndInfoList = {{
{Feature::TextureCompressionBC,
{"texture-compression-bc", "Support Block Compressed (BC) texture formats",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=42"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=42", FeatureInfo::FeatureState::Stable}},
{Feature::TextureCompressionETC2,
{"texture-compression-etc2",
"Support Ericsson Texture Compressed (ETC2/EAC) texture "
"formats",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=955"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=955", FeatureInfo::FeatureState::Stable}},
{Feature::TextureCompressionASTC,
{"texture-compression-astc",
"Support Adaptable Scalable Texture Compressed (ASTC) "
"texture formats",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=955"}},
- {Feature::ShaderFloat16,
- {"shader-float16",
- "Support 16bit float arithmetic and declarations in uniform and storage buffers",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=426"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=955", FeatureInfo::FeatureState::Stable}},
{Feature::PipelineStatisticsQuery,
{"pipeline-statistics-query", "Support Pipeline Statistics Query",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=434"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=434", FeatureInfo::FeatureState::Stable}},
{Feature::TimestampQuery,
{"timestamp-query", "Support Timestamp Query",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=434"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=434", FeatureInfo::FeatureState::Stable}},
{Feature::DepthClipControl,
{"depth-clip-control", "Disable depth clipping of primitives to the clip volume",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=1178"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=1178", FeatureInfo::FeatureState::Stable}},
{Feature::Depth32FloatStencil8,
{"depth32float-stencil8", "Support depth32float-stencil8 texture format",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=690"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=690", FeatureInfo::FeatureState::Stable}},
{Feature::ChromiumExperimentalDp4a,
{"chromium-experimental-dp4a", "Support experimental DP4a instructions in WGSL",
- "https://bugs.chromium.org/p/tint/issues/detail?id=1497"}},
+ "https://bugs.chromium.org/p/tint/issues/detail?id=1497",
+ FeatureInfo::FeatureState::Experimental}},
{Feature::IndirectFirstInstance,
{"indirect-first-instance", "Support non-zero first instance values on indirect draw calls",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=1197"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=1197", FeatureInfo::FeatureState::Stable}},
+ {Feature::ShaderF16,
+ {"shader-f16", "Supports the \"enable f16;\" directive in WGSL",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=1510",
+ FeatureInfo::FeatureState::Experimental}},
{Feature::DawnInternalUsages,
{"dawn-internal-usages",
"Add internal usages to resources to affect how the texture is allocated, but not "
"frontend validation. Other internal commands may access this usage.",
"https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/dawn/features/"
- "dawn_internal_usages.md"}},
+ "dawn_internal_usages.md",
+ FeatureInfo::FeatureState::Stable}},
{Feature::MultiPlanarFormats,
{"multiplanar-formats", "Import and use multi-planar texture formats with per plane views",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=551"}},
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=551", FeatureInfo::FeatureState::Stable}},
{Feature::DawnNative,
{"dawn-native", "WebGPU is running on top of dawn_native.",
"https://dawn.googlesource.com/dawn/+/refs/heads/main/docs/dawn/features/"
- "dawn_native.md"}},
+ "dawn_native.md",
+ FeatureInfo::FeatureState::Stable}},
}};
Feature FromAPIFeature(wgpu::FeatureName feature) {
switch (feature) {
case wgpu::FeatureName::Undefined:
return Feature::InvalidEnum;
+ case wgpu::FeatureName::DawnShaderFloat16:
+ // Deprecated.
+ return Feature::InvalidEnum;
case wgpu::FeatureName::TimestampQuery:
return Feature::TimestampQuery;
@@ -103,8 +109,6 @@
return Feature::Depth32FloatStencil8;
case wgpu::FeatureName::IndirectFirstInstance:
return Feature::IndirectFirstInstance;
- case wgpu::FeatureName::DawnShaderFloat16:
- return Feature::ShaderFloat16;
case wgpu::FeatureName::DawnInternalUsages:
return Feature::DawnInternalUsages;
case wgpu::FeatureName::DawnMultiPlanarFormats:
@@ -113,6 +117,8 @@
return Feature::DawnNative;
case wgpu::FeatureName::ChromiumExperimentalDp4a:
return Feature::ChromiumExperimentalDp4a;
+ case wgpu::FeatureName::ShaderF16:
+ return Feature::ShaderF16;
}
return Feature::InvalidEnum;
}
@@ -135,8 +141,6 @@
return wgpu::FeatureName::Depth32FloatStencil8;
case Feature::IndirectFirstInstance:
return wgpu::FeatureName::IndirectFirstInstance;
- case Feature::ShaderFloat16:
- return wgpu::FeatureName::DawnShaderFloat16;
case Feature::DawnInternalUsages:
return wgpu::FeatureName::DawnInternalUsages;
case Feature::MultiPlanarFormats:
@@ -145,6 +149,8 @@
return wgpu::FeatureName::DawnNative;
case Feature::ChromiumExperimentalDp4a:
return wgpu::FeatureName::ChromiumExperimentalDp4a;
+ case Feature::ShaderF16:
+ return wgpu::FeatureName::ShaderF16;
case Feature::EnumCount:
break;
diff --git a/src/dawn/native/Features.h b/src/dawn/native/Features.h
index f97fd9d..9413da6 100644
--- a/src/dawn/native/Features.h
+++ b/src/dawn/native/Features.h
@@ -30,13 +30,13 @@
TextureCompressionBC,
TextureCompressionETC2,
TextureCompressionASTC,
- ShaderFloat16,
PipelineStatisticsQuery,
TimestampQuery,
DepthClipControl,
Depth32FloatStencil8,
ChromiumExperimentalDp4a,
IndirectFirstInstance,
+ ShaderF16,
// Dawn-specific
DawnInternalUsages,
diff --git a/src/dawn/native/Format.cpp b/src/dawn/native/Format.cpp
index 11de9ac..ef9a7d2 100644
--- a/src/dawn/native/Format.cpp
+++ b/src/dawn/native/Format.cpp
@@ -389,12 +389,12 @@
AddMultiAspectFormat(wgpu::TextureFormat::Depth24PlusStencil8,
Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8, true, true, true, 2);
AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4, true);
- bool isD32S8Supported = device->IsFeatureEnabled(Feature::Depth32FloatStencil8);
+ bool isD32S8Supported = device->HasFeature(Feature::Depth32FloatStencil8);
AddMultiAspectFormat(wgpu::TextureFormat::Depth32FloatStencil8,
Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Stencil8, true, isD32S8Supported, true, 2);
// BC compressed formats
- bool isBCFormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionBC);
+ bool isBCFormatSupported = device->HasFeature(Feature::TextureCompressionBC);
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC1RGBAUnorm);
AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported, 1);
@@ -411,7 +411,7 @@
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC7RGBAUnorm);
// ETC2/EAC compressed formats
- bool isETC2FormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionETC2);
+ bool isETC2FormatSupported = device->HasFeature(Feature::TextureCompressionETC2);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, 8, 4, 4, isETC2FormatSupported, 3);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, 8, 4, 4, isETC2FormatSupported, 3, wgpu::TextureFormat::ETC2RGB8Unorm);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, 8, 4, 4, isETC2FormatSupported, 4);
@@ -424,7 +424,7 @@
AddCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, 16, 4, 4, isETC2FormatSupported, 2);
// ASTC compressed formats
- bool isASTCFormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionASTC);
+ bool isASTCFormatSupported = device->HasFeature(Feature::TextureCompressionASTC);
AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC4x4Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, isASTCFormatSupported, 4);
@@ -455,7 +455,7 @@
AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC12x12Unorm);
// multi-planar formats
- const bool isMultiPlanarFormatSupported = device->IsFeatureEnabled(Feature::MultiPlanarFormats);
+ const bool isMultiPlanarFormatSupported = device->HasFeature(Feature::MultiPlanarFormats);
AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, false, isMultiPlanarFormatSupported, false, 3);
diff --git a/src/dawn/native/IndirectDrawValidationEncoder.cpp b/src/dawn/native/IndirectDrawValidationEncoder.cpp
index abd09cd..db940e7 100644
--- a/src/dawn/native/IndirectDrawValidationEncoder.cpp
+++ b/src/dawn/native/IndirectDrawValidationEncoder.cpp
@@ -338,7 +338,7 @@
if (device->IsValidationEnabled()) {
newPass.flags |= kValidationEnabled;
}
- if (device->IsFeatureEnabled(Feature::IndirectFirstInstance)) {
+ if (device->HasFeature(Feature::IndirectFirstInstance)) {
newPass.flags |= kIndirectFirstInstanceEnabled;
}
passes.push_back(std::move(newPass));
diff --git a/src/dawn/native/QuerySet.cpp b/src/dawn/native/QuerySet.cpp
index a503165..ad75bed 100644
--- a/src/dawn/native/QuerySet.cpp
+++ b/src/dawn/native/QuerySet.cpp
@@ -60,7 +60,7 @@
"fully implemented");
DAWN_INVALID_IF(
- !device->IsFeatureEnabled(Feature::PipelineStatisticsQuery),
+ !device->HasFeature(Feature::PipelineStatisticsQuery),
"Pipeline statistics query set created without the feature being enabled.");
DAWN_INVALID_IF(descriptor->pipelineStatisticsCount == 0,
@@ -82,7 +82,7 @@
"Timestamp queries are disallowed because they may expose precise "
"timing information.");
- DAWN_INVALID_IF(!device->IsFeatureEnabled(Feature::TimestampQuery),
+ DAWN_INVALID_IF(!device->HasFeature(Feature::TimestampQuery),
"Timestamp query set created without the feature being enabled.");
DAWN_INVALID_IF(descriptor->pipelineStatisticsCount != 0,
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index 8a3d82a..03b90bb 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -156,7 +156,7 @@
DAWN_TRY(ValidateSingleSType(descriptor->nextInChain, wgpu::SType::PrimitiveDepthClipControl));
const PrimitiveDepthClipControl* depthClipControl = nullptr;
FindInChain(descriptor->nextInChain, &depthClipControl);
- DAWN_INVALID_IF(depthClipControl && !device->IsFeatureEnabled(Feature::DepthClipControl),
+ DAWN_INVALID_IF(depthClipControl && !device->HasFeature(Feature::DepthClipControl),
"%s is not supported", wgpu::FeatureName::DepthClipControl);
DAWN_TRY(ValidatePrimitiveTopology(descriptor->topology));
DAWN_TRY(ValidateIndexFormat(descriptor->stripIndexFormat));
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index 7efbbf8..5ddbbc3 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -339,7 +339,7 @@
FindInChain(descriptor->nextInChain, &internalUsageDesc);
DAWN_INVALID_IF(
- internalUsageDesc != nullptr && !device->IsFeatureEnabled(Feature::DawnInternalUsages),
+ internalUsageDesc != nullptr && !device->HasFeature(Feature::DawnInternalUsages),
"The internalUsageDesc is not empty while the dawn-internal-usages feature is not enabled");
const Format* format;
diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp
index 8fbf0e3..3816f20 100644
--- a/src/dawn/native/Toggles.cpp
+++ b/src/dawn/native/Toggles.cpp
@@ -17,6 +17,7 @@
#include "dawn/common/Assert.h"
#include "dawn/common/BitSetIterator.h"
#include "dawn/native/Toggles.h"
+#include "dawn/native/dawn_platform.h"
namespace dawn::native {
namespace {
@@ -334,6 +335,81 @@
return togglesNameInUse;
}
+TripleStateTogglesSet TripleStateTogglesSet::CreateFromTogglesDeviceDescriptor(
+ const DawnTogglesDeviceDescriptor* togglesDesc) {
+ TripleStateTogglesSet userToggles;
+ if (togglesDesc != nullptr) {
+ TogglesInfo togglesInfo;
+ for (uint32_t i = 0; i < togglesDesc->forceEnabledTogglesCount; ++i) {
+ Toggle toggle = togglesInfo.ToggleNameToEnum(togglesDesc->forceEnabledToggles[i]);
+ if (toggle != Toggle::InvalidEnum) {
+ userToggles.togglesIsProvided.Set(toggle, true);
+ userToggles.providedTogglesEnabled.Set(toggle, true);
+ }
+ }
+ for (uint32_t i = 0; i < togglesDesc->forceDisabledTogglesCount; ++i) {
+ Toggle toggle = togglesInfo.ToggleNameToEnum(togglesDesc->forceDisabledToggles[i]);
+ if (toggle != Toggle::InvalidEnum) {
+ userToggles.togglesIsProvided.Set(toggle, true);
+ userToggles.providedTogglesEnabled.Set(toggle, false);
+ }
+ }
+ }
+ return userToggles;
+}
+
+void TripleStateTogglesSet::Set(Toggle toggle, bool enabled) {
+ ASSERT(toggle != Toggle::InvalidEnum);
+ togglesIsProvided.Set(toggle, true);
+ providedTogglesEnabled.Set(toggle, enabled);
+}
+
+bool TripleStateTogglesSet::IsProvided(Toggle toggle) const {
+ return togglesIsProvided.Has(toggle);
+}
+// Return true if the toggle is provided in enable list, and false otherwise.
+bool TripleStateTogglesSet::IsEnabled(Toggle toggle) const {
+ return togglesIsProvided.Has(toggle) && providedTogglesEnabled.Has(toggle);
+}
+// Return true if the toggle is provided in disable list, and false otherwise.
+bool TripleStateTogglesSet::IsDisabled(Toggle toggle) const {
+ return togglesIsProvided.Has(toggle) && !providedTogglesEnabled.Has(toggle);
+}
+
+std::vector<const char*> TripleStateTogglesSet::GetEnabledToggleNames() const {
+ std::vector<const char*> enabledTogglesName(providedTogglesEnabled.toggleBitset.count());
+
+ uint32_t index = 0;
+ for (uint32_t i : IterateBitSet(providedTogglesEnabled.toggleBitset)) {
+ const Toggle& toggle = static_cast<Toggle>(i);
+ // All enabled toggles must be provided.
+ ASSERT(togglesIsProvided.Has(toggle));
+ const char* toggleName = ToggleEnumToName(toggle);
+ enabledTogglesName[index] = toggleName;
+ ++index;
+ }
+
+ return enabledTogglesName;
+}
+
+std::vector<const char*> TripleStateTogglesSet::GetDisabledToggleNames() const {
+ std::vector<const char*> enabledTogglesName(togglesIsProvided.toggleBitset.count() -
+ providedTogglesEnabled.toggleBitset.count());
+
+ uint32_t index = 0;
+ for (uint32_t i : IterateBitSet(togglesIsProvided.toggleBitset)) {
+ const Toggle& toggle = static_cast<Toggle>(i);
+ // Disabled toggles are those provided but not enabled.
+ if (!providedTogglesEnabled.Has(toggle)) {
+ const char* toggleName = ToggleEnumToName(toggle);
+ enabledTogglesName[index] = toggleName;
+ ++index;
+ }
+ }
+
+ return enabledTogglesName;
+}
+
const char* ToggleEnumToName(Toggle toggle) {
ASSERT(toggle != Toggle::InvalidEnum);
diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h
index 5e000f9..981aa94 100644
--- a/src/dawn/native/Toggles.h
+++ b/src/dawn/native/Toggles.h
@@ -24,6 +24,8 @@
namespace dawn::native {
+struct DawnTogglesDeviceDescriptor;
+
enum class Toggle {
EmulateStoreAndMSAAResolve,
NonzeroClearResourcesOnCreationForTesting,
@@ -92,6 +94,27 @@
std::vector<const char*> GetContainedToggleNames() const;
};
+// TripleStateTogglesSet track each toggle with three posible states, i.e. "Not provided" (default),
+// "Provided as enabled", and "Provided as disabled". This struct can be used to record the
+// user-provided toggles, where some toggles are explicitly enabled or disabled while the other
+// toggles are left as default.
+struct TripleStateTogglesSet {
+ TogglesSet togglesIsProvided;
+ TogglesSet providedTogglesEnabled;
+
+ static TripleStateTogglesSet CreateFromTogglesDeviceDescriptor(
+ const DawnTogglesDeviceDescriptor* togglesDesc);
+ // Provide a single toggle with given state.
+ void Set(Toggle toggle, bool enabled);
+ bool IsProvided(Toggle toggle) const;
+ // Return true if the toggle is provided in enable list, and false otherwise.
+ bool IsEnabled(Toggle toggle) const;
+ // Return true if the toggle is provided in disable list, and false otherwise.
+ bool IsDisabled(Toggle toggle) const;
+ std::vector<const char*> GetEnabledToggleNames() const;
+ std::vector<const char*> GetDisabledToggleNames() const;
+};
+
const char* ToggleEnumToName(Toggle toggle);
class TogglesInfo {
diff --git a/src/dawn/native/d3d12/AdapterD3D12.cpp b/src/dawn/native/d3d12/AdapterD3D12.cpp
index e23830e..bcd40fc 100644
--- a/src/dawn/native/d3d12/AdapterD3D12.cpp
+++ b/src/dawn/native/d3d12/AdapterD3D12.cpp
@@ -147,6 +147,9 @@
dxcVersion >= MakeDXCVersion(kLeastMajorVersionForDP4a, kLeastMinorVersionForDP4a)) {
mSupportedFeatures.EnableFeature(Feature::ChromiumExperimentalDp4a);
}
+ if (mDeviceInfo.supportsShaderF16) {
+ mSupportedFeatures.EnableFeature(Feature::ShaderF16);
+ }
}
return {};
@@ -312,6 +315,20 @@
return {};
}
+MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ // shader-f16 feature and chromium-experimental-dp4a feature require DXC for D3D12.
+ if (feature == wgpu::FeatureName::ShaderF16 ||
+ feature == wgpu::FeatureName::ChromiumExperimentalDp4a) {
+ DAWN_INVALID_IF(!(userProvidedToggles.IsEnabled(Toggle::UseDXC) &&
+ mBackend->GetFunctions()->IsDXCAvailable()),
+ "Feature %s requires DXC for D3D12.",
+ GetInstance()->GetFeatureInfo(feature)->name);
+ }
+ return {};
+}
+
MaybeError Adapter::InitializeDebugLayerFilters() {
if (!GetInstance()->IsBackendValidationEnabled()) {
return {};
@@ -418,8 +435,10 @@
infoQueue->PopStorageFilter();
}
-ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
- return Device::Create(this, descriptor);
+ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ return Device::Create(this, descriptor, userProvidedToggles);
}
// Resets the backend device and creates a new one. If any D3D12 objects belonging to the
diff --git a/src/dawn/native/d3d12/AdapterD3D12.h b/src/dawn/native/d3d12/AdapterD3D12.h
index 035e291..2c8a377 100644
--- a/src/dawn/native/d3d12/AdapterD3D12.h
+++ b/src/dawn/native/d3d12/AdapterD3D12.h
@@ -40,7 +40,9 @@
const gpu_info::D3DDriverVersion& GetDriverVersion() const;
private:
- ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) override;
MaybeError ResetInternalDeviceForTestingImpl() override;
bool AreTimestampQueriesSupported() const;
@@ -49,6 +51,10 @@
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
+ MaybeError ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) override;
+
MaybeError InitializeDebugLayerFilters();
void CleanUpDebugLayerFilters();
diff --git a/src/dawn/native/d3d12/D3D12Info.cpp b/src/dawn/native/d3d12/D3D12Info.cpp
index 3d3470c..d6d8dde 100644
--- a/src/dawn/native/d3d12/D3D12Info.cpp
+++ b/src/dawn/native/d3d12/D3D12Info.cpp
@@ -121,7 +121,7 @@
info.shaderProfiles[SingleShaderStage::Fragment] = L"p" + profileSuffix;
info.shaderProfiles[SingleShaderStage::Compute] = L"c" + profileSuffix;
- info.supportsShaderFloat16 =
+ info.supportsShaderF16 =
driverShaderModel >= D3D_SHADER_MODEL_6_2 && featureOptions4.Native16BitShaderOpsSupported;
info.supportsDP4a = driverShaderModel >= D3D_SHADER_MODEL_6_4;
diff --git a/src/dawn/native/d3d12/D3D12Info.h b/src/dawn/native/d3d12/D3D12Info.h
index f81e28d..af0b633 100644
--- a/src/dawn/native/d3d12/D3D12Info.h
+++ b/src/dawn/native/d3d12/D3D12Info.h
@@ -27,7 +27,7 @@
bool isUMA;
uint32_t resourceHeapTier;
bool supportsRenderPass;
- bool supportsShaderFloat16;
+ bool supportsShaderF16;
// shaderModel indicates the maximum supported shader model, for example, the value 62
// indicates that current driver supports the maximum shader model is shader model 6.2.
uint32_t shaderModel;
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index 2a6c97f..4a6a1bd 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -63,8 +63,10 @@
static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
// static
-ResultOrError<Ref<Device>> Device::Create(Adapter* adapter, const DeviceDescriptor* descriptor) {
- Ref<Device> device = AcquireRef(new Device(adapter, descriptor));
+ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ Ref<Device> device = AcquireRef(new Device(adapter, descriptor, userProvidedToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
@@ -84,7 +86,7 @@
CheckHRESULT(mD3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)),
"D3D12 create command queue"));
- if (IsFeatureEnabled(Feature::TimestampQuery) &&
+ if (HasFeature(Feature::TimestampQuery) &&
!IsToggleEnabled(Toggle::DisableTimestampQueryConversion)) {
// Get GPU timestamp counter frequency (in ticks/second). This fails if the specified
// command queue doesn't support timestamps. D3D12_COMMAND_LIST_TYPE_DIRECT queues
@@ -876,17 +878,6 @@
return ToBackend(computePipeline)->UsesNumWorkgroups();
}
-bool Device::IsFeatureEnabled(Feature feature) const {
- // Currently we can only use DXC to compile HLSL shaders using float16, and
- // ChromiumExperimentalDp4a is an experimental feature which can only be enabled with toggle
- // "use_dxc".
- if ((feature == Feature::ChromiumExperimentalDp4a || feature == Feature::ShaderFloat16) &&
- !IsToggleEnabled(Toggle::UseDXC)) {
- return false;
- }
- return DeviceBase::IsFeatureEnabled(feature);
-}
-
void Device::SetLabelImpl() {
SetDebugName(this, mD3d12Device.Get(), "Dawn_Device", GetLabel());
}
diff --git a/src/dawn/native/d3d12/DeviceD3D12.h b/src/dawn/native/d3d12/DeviceD3D12.h
index 49bc301..6b56d1a 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.h
+++ b/src/dawn/native/d3d12/DeviceD3D12.h
@@ -46,7 +46,9 @@
// Definition of backend types
class Device final : public DeviceBase {
public:
- static ResultOrError<Ref<Device>> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
+ static ResultOrError<Ref<Device>> Create(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@@ -160,8 +162,6 @@
bool ShouldDuplicateParametersForDrawIndirect(
const RenderPipelineBase* renderPipelineBase) const override;
- bool IsFeatureEnabled(Feature feature) const override;
-
uint64_t GetBufferCopyOffsetAlignmentForDepthStencil() const override;
// Dawn APIs
diff --git a/src/dawn/native/d3d12/ShaderModuleD3D12.cpp b/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
index bb0077a..f67167e 100644
--- a/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
+++ b/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
@@ -97,7 +97,7 @@
X(bool, dumpShaders)
#define D3D_BYTECODE_COMPILATION_REQUEST_MEMBERS(X) \
- X(bool, hasShaderFloat16Feature) \
+ X(bool, hasShaderF16Feature) \
X(uint32_t, compileFlags) \
X(Compiler, compiler) \
X(uint64_t, compilerVersion) \
@@ -186,8 +186,7 @@
std::wstring entryPointW;
DAWN_TRY_ASSIGN(entryPointW, ConvertStringToWstring(entryPointName));
- std::vector<const wchar_t*> arguments =
- GetDXCArguments(r.compileFlags, r.hasShaderFloat16Feature);
+ std::vector<const wchar_t*> arguments = GetDXCArguments(r.compileFlags, r.hasShaderF16Feature);
ComPtr<IDxcOperationResult> result;
DAWN_TRY(CheckHRESULT(r.dxcCompiler->Compile(sourceBlob.Get(), nullptr, entryPointW.c_str(),
@@ -475,7 +474,7 @@
req.hlsl.disableWorkgroupInit = device->IsToggleEnabled(Toggle::DisableWorkgroupInit);
req.hlsl.dumpShaders = device->IsToggleEnabled(Toggle::DumpShaders);
- req.bytecode.hasShaderFloat16Feature = device->IsFeatureEnabled(Feature::ShaderFloat16);
+ req.bytecode.hasShaderF16Feature = device->HasFeature(Feature::ShaderF16);
req.bytecode.compileFlags = compileFlags;
if (device->IsToggleEnabled(Toggle::UseDXC)) {
diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm
index acba1a9..3ef6f3f 100644
--- a/src/dawn/native/metal/BackendMTL.mm
+++ b/src/dawn/native/metal/BackendMTL.mm
@@ -299,8 +299,10 @@
}
private:
- ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
- return Device::Create(this, mDevice, descriptor);
+ ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) override {
+ return Device::Create(this, mDevice, descriptor, userProvidedToggles);
}
MaybeError InitializeImpl() override { return {}; }
@@ -378,6 +380,8 @@
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
+ mSupportedFeatures.EnableFeature(Feature::ShaderF16);
+
return {};
}
@@ -620,6 +624,12 @@
return {};
}
+ MaybeError ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) override {
+ return {};
+ }
+
NSPRef<id<MTLDevice>> mDevice;
};
diff --git a/src/dawn/native/metal/DeviceMTL.h b/src/dawn/native/metal/DeviceMTL.h
index 074140b..62d4f90 100644
--- a/src/dawn/native/metal/DeviceMTL.h
+++ b/src/dawn/native/metal/DeviceMTL.h
@@ -38,7 +38,8 @@
public:
static ResultOrError<Ref<Device>> Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
- const DeviceDescriptor* descriptor);
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@@ -74,7 +75,8 @@
private:
Device(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
- const DeviceDescriptor* descriptor);
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
diff --git a/src/dawn/native/metal/DeviceMTL.mm b/src/dawn/native/metal/DeviceMTL.mm
index 4b589ea..a3fdac1 100644
--- a/src/dawn/native/metal/DeviceMTL.mm
+++ b/src/dawn/native/metal/DeviceMTL.mm
@@ -107,16 +107,21 @@
// static
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));
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ Ref<Device> device =
+ AcquireRef(new Device(adapter, std::move(mtlDevice), descriptor, userProvidedToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
Device::Device(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
- const DeviceDescriptor* descriptor)
- : DeviceBase(adapter, descriptor), mMtlDevice(std::move(mtlDevice)), mCompletedSerial(0) {}
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles)
+ : DeviceBase(adapter, descriptor, userProvidedToggles),
+ mMtlDevice(std::move(mtlDevice)),
+ mCompletedSerial(0) {}
Device::~Device() {
Destroy();
@@ -132,7 +137,7 @@
DAWN_TRY(mCommandContext.PrepareNextCommandBuffer(*mCommandQueue));
- if (IsFeatureEnabled(Feature::TimestampQuery) &&
+ if (HasFeature(Feature::TimestampQuery) &&
!IsToggleEnabled(Toggle::DisableTimestampQueryConversion)) {
// Make a best guess of timestamp period based on device vendor info, and converge it to
// an accurate value by the following calculations.
@@ -322,7 +327,7 @@
DAWN_TRY(SubmitPendingCommandBuffer());
// Just run timestamp period calculation when timestamp feature is enabled.
- if (IsFeatureEnabled(Feature::TimestampQuery)) {
+ if (HasFeature(Feature::TimestampQuery)) {
if (@available(macos 10.15, iOS 14.0, *)) {
UpdateTimestampPeriod(GetMTLDevice(), mKalmanInfo.get(), &mCpuTimestamp, &mGpuTimestamp,
&mTimestampPeriod);
diff --git a/src/dawn/native/null/DeviceNull.cpp b/src/dawn/native/null/DeviceNull.cpp
index a00515d..79d5f66 100644
--- a/src/dawn/native/null/DeviceNull.cpp
+++ b/src/dawn/native/null/DeviceNull.cpp
@@ -65,8 +65,16 @@
return {};
}
-ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
- return Device::Create(this, descriptor);
+ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ return Device::Create(this, descriptor, userProvidedToggles);
+}
+
+MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ return {};
}
class Backend : public BackendConnection {
@@ -103,8 +111,10 @@
// Device
// static
-ResultOrError<Ref<Device>> Device::Create(Adapter* adapter, const DeviceDescriptor* descriptor) {
- Ref<Device> device = AcquireRef(new Device(adapter, descriptor));
+ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ Ref<Device> device = AcquireRef(new Device(adapter, descriptor, userProvidedToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
diff --git a/src/dawn/native/null/DeviceNull.h b/src/dawn/native/null/DeviceNull.h
index 74da890..7c90c4e 100644
--- a/src/dawn/native/null/DeviceNull.h
+++ b/src/dawn/native/null/DeviceNull.h
@@ -89,7 +89,9 @@
class Device final : public DeviceBase {
public:
- static ResultOrError<Ref<Device>> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
+ static ResultOrError<Ref<Device>> Create(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@@ -182,7 +184,13 @@
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
- ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) override;
+
+ MaybeError ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) override;
};
// Helper class so |BindGroup| can allocate memory for its binding data,
diff --git a/src/dawn/native/opengl/AdapterGL.cpp b/src/dawn/native/opengl/AdapterGL.cpp
index 7a4f336..f309c61 100644
--- a/src/dawn/native/opengl/AdapterGL.cpp
+++ b/src/dawn/native/opengl/AdapterGL.cpp
@@ -141,6 +141,11 @@
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
}
+ // ShaderF16
+ if (mFunctions.IsGLExtensionSupported("GL_AMD_gpu_shader_half_float")) {
+ mSupportedFeatures.EnableFeature(Feature::ShaderF16);
+ }
+
return {};
}
@@ -149,12 +154,20 @@
return {};
}
-ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
+ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
EGLenum api =
GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API;
std::unique_ptr<Device::Context> context;
DAWN_TRY_ASSIGN(context, ContextEGL::Create(mEGLFunctions, api));
- return Device::Create(this, descriptor, mFunctions, std::move(context));
+ return Device::Create(this, descriptor, mFunctions, std::move(context), userProvidedToggles);
+}
+
+MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ return {};
}
} // namespace dawn::native::opengl
diff --git a/src/dawn/native/opengl/AdapterGL.h b/src/dawn/native/opengl/AdapterGL.h
index 6e354b2..4d6b0c1 100644
--- a/src/dawn/native/opengl/AdapterGL.h
+++ b/src/dawn/native/opengl/AdapterGL.h
@@ -36,7 +36,13 @@
MaybeError InitializeImpl() override;
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
- ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) override;
+
+ MaybeError ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) override;
OpenGLFunctions mFunctions;
EGLFunctions mEGLFunctions;
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index 4246d5f..8297573 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -108,8 +108,10 @@
ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
- std::unique_ptr<Context> context) {
- Ref<Device> device = AcquireRef(new Device(adapter, descriptor, functions, std::move(context)));
+ std::unique_ptr<Context> context,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ Ref<Device> device = AcquireRef(
+ new Device(adapter, descriptor, functions, std::move(context), userProvidedToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
@@ -117,8 +119,11 @@
Device::Device(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
- std::unique_ptr<Context> context)
- : DeviceBase(adapter, descriptor), mGL(functions), mContext(std::move(context)) {}
+ std::unique_ptr<Context> context,
+ const TripleStateTogglesSet& userProvidedToggles)
+ : DeviceBase(adapter, descriptor, userProvidedToggles),
+ mGL(functions),
+ mContext(std::move(context)) {}
Device::~Device() {
Destroy();
diff --git a/src/dawn/native/opengl/DeviceGL.h b/src/dawn/native/opengl/DeviceGL.h
index 78abf11..08c776b 100644
--- a/src/dawn/native/opengl/DeviceGL.h
+++ b/src/dawn/native/opengl/DeviceGL.h
@@ -43,7 +43,8 @@
static ResultOrError<Ref<Device>> Create(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
- std::unique_ptr<Context> context);
+ std::unique_ptr<Context> context,
+ const TripleStateTogglesSet& userProvidedToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@@ -93,7 +94,8 @@
Device(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
- std::unique_ptr<Context> context);
+ std::unique_ptr<Context> context,
+ const TripleStateTogglesSet& userProvidedToggles);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp
index 9ccc4d6..ab0342b 100644
--- a/src/dawn/native/vulkan/AdapterVk.cpp
+++ b/src/dawn/native/vulkan/AdapterVk.cpp
@@ -159,6 +159,15 @@
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
}
+ if (mDeviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
+ mDeviceInfo.HasExt(DeviceExt::_16BitStorage) &&
+ mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
+ mDeviceInfo._16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE &&
+ mDeviceInfo._16BitStorageFeatures.storageInputOutput16 == VK_TRUE &&
+ mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE) {
+ mSupportedFeatures.EnableFeature(Feature::ShaderF16);
+ }
+
if (mDeviceInfo.HasExt(DeviceExt::ShaderIntegerDotProduct) &&
mDeviceInfo.shaderIntegerDotProductProperties
.integerDotProduct4x8BitPackedSignedAccelerated == VK_TRUE &&
@@ -354,8 +363,16 @@
mVulkanInstance->GetFunctions());
}
-ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
- return Device::Create(this, descriptor);
+ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ return Device::Create(this, descriptor, userProvidedToggles);
+}
+
+MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ return {};
}
} // namespace dawn::native::vulkan
diff --git a/src/dawn/native/vulkan/AdapterVk.h b/src/dawn/native/vulkan/AdapterVk.h
index 9cb5234..a7232fb 100644
--- a/src/dawn/native/vulkan/AdapterVk.h
+++ b/src/dawn/native/vulkan/AdapterVk.h
@@ -46,7 +46,13 @@
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
- ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) override;
+
+ MaybeError ValidateFeatureSupportedWithTogglesImpl(
+ wgpu::FeatureName feature,
+ const TripleStateTogglesSet& userProvidedToggles) override;
VkPhysicalDevice mPhysicalDevice;
Ref<VulkanInstance> mVulkanInstance;
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp
index 662fa5a..b9902ab 100644
--- a/src/dawn/native/vulkan/DeviceVk.cpp
+++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -78,14 +78,19 @@
} // namespace
// static
-ResultOrError<Ref<Device>> Device::Create(Adapter* adapter, const DeviceDescriptor* descriptor) {
- Ref<Device> device = AcquireRef(new Device(adapter, descriptor));
+ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles) {
+ Ref<Device> device = AcquireRef(new Device(adapter, descriptor, userProvidedToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
-Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor)
- : DeviceBase(adapter, descriptor), mDebugPrefix(GetNextDeviceDebugPrefix()) {
+Device::Device(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles)
+ : DeviceBase(adapter, descriptor, userProvidedToggles),
+ mDebugPrefix(GetNextDeviceDebugPrefix()) {
InitTogglesFromDriver();
}
@@ -449,29 +454,29 @@
usedKnobs.features.samplerAnisotropy = VK_TRUE;
}
- if (IsFeatureEnabled(Feature::TextureCompressionBC)) {
+ if (HasFeature(Feature::TextureCompressionBC)) {
ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.textureCompressionBC == VK_TRUE);
usedKnobs.features.textureCompressionBC = VK_TRUE;
}
- if (IsFeatureEnabled(Feature::TextureCompressionETC2)) {
+ if (HasFeature(Feature::TextureCompressionETC2)) {
ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.textureCompressionETC2 == VK_TRUE);
usedKnobs.features.textureCompressionETC2 = VK_TRUE;
}
- if (IsFeatureEnabled(Feature::TextureCompressionASTC)) {
+ if (HasFeature(Feature::TextureCompressionASTC)) {
ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.textureCompressionASTC_LDR ==
VK_TRUE);
usedKnobs.features.textureCompressionASTC_LDR = VK_TRUE;
}
- if (IsFeatureEnabled(Feature::PipelineStatisticsQuery)) {
+ if (HasFeature(Feature::PipelineStatisticsQuery)) {
ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.pipelineStatisticsQuery ==
VK_TRUE);
usedKnobs.features.pipelineStatisticsQuery = VK_TRUE;
}
- if (IsFeatureEnabled(Feature::DepthClipControl)) {
+ if (HasFeature(Feature::DepthClipControl)) {
const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
ASSERT(deviceInfo.HasExt(DeviceExt::DepthClipEnable) &&
deviceInfo.depthClipEnableFeatures.depthClipEnable == VK_TRUE);
@@ -481,16 +486,20 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT);
}
- if (IsFeatureEnabled(Feature::ShaderFloat16)) {
+ // TODO(dawn:1510, tint:1473): After implementing a transform to handle the pipeline input /
+ // output if necessary, relax the requirement of storageInputOutput16.
+ if (HasFeature(Feature::ShaderF16)) {
const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
ASSERT(deviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
deviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
deviceInfo.HasExt(DeviceExt::_16BitStorage) &&
deviceInfo._16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE &&
+ deviceInfo._16BitStorageFeatures.storageInputOutput16 == VK_TRUE &&
deviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE);
usedKnobs.shaderFloat16Int8Features.shaderFloat16 = VK_TRUE;
usedKnobs._16BitStorageFeatures.storageBuffer16BitAccess = VK_TRUE;
+ usedKnobs._16BitStorageFeatures.storageInputOutput16 = VK_TRUE;
usedKnobs._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess = VK_TRUE;
featuresChain.Add(&usedKnobs.shaderFloat16Int8Features,
diff --git a/src/dawn/native/vulkan/DeviceVk.h b/src/dawn/native/vulkan/DeviceVk.h
index 6e88d4c..fa27f82 100644
--- a/src/dawn/native/vulkan/DeviceVk.h
+++ b/src/dawn/native/vulkan/DeviceVk.h
@@ -43,7 +43,9 @@
class Device final : public DeviceBase {
public:
- static ResultOrError<Ref<Device>> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
+ static ResultOrError<Ref<Device>> Create(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@@ -113,7 +115,9 @@
const char* GetDebugPrefix() { return mDebugPrefix.c_str(); }
private:
- Device(Adapter* adapter, const DeviceDescriptor* descriptor);
+ Device(Adapter* adapter,
+ const DeviceDescriptor* descriptor,
+ const TripleStateTogglesSet& userProvidedToggles);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
diff --git a/src/dawn/native/vulkan/RenderPipelineVk.cpp b/src/dawn/native/vulkan/RenderPipelineVk.cpp
index 830e012..df61ac7 100644
--- a/src/dawn/native/vulkan/RenderPipelineVk.cpp
+++ b/src/dawn/native/vulkan/RenderPipelineVk.cpp
@@ -436,7 +436,7 @@
PNextChainBuilder rasterizationChain(&rasterization);
VkPipelineRasterizationDepthClipStateCreateInfoEXT depthClipState;
if (HasUnclippedDepth()) {
- ASSERT(device->IsFeatureEnabled(Feature::DepthClipControl));
+ ASSERT(device->HasFeature(Feature::DepthClipControl));
depthClipState.pNext = nullptr;
depthClipState.depthClipEnable = VK_FALSE;
depthClipState.flags = 0;
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 2955a8b..6f5ba74 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -488,7 +488,7 @@
"end2end/SamplerFilterAnisotropicTests.cpp",
"end2end/SamplerTests.cpp",
"end2end/ScissorTests.cpp",
- "end2end/ShaderFloat16Tests.cpp",
+ "end2end/ShaderF16Tests.cpp",
"end2end/ShaderTests.cpp",
"end2end/ShaderValidationTests.cpp",
"end2end/StorageTextureTests.cpp",
diff --git a/src/dawn/tests/end2end/ExperimentalDP4aTests.cpp b/src/dawn/tests/end2end/ExperimentalDP4aTests.cpp
index e6ecf3a..d77de5b 100644
--- a/src/dawn/tests/end2end/ExperimentalDP4aTests.cpp
+++ b/src/dawn/tests/end2end/ExperimentalDP4aTests.cpp
@@ -31,7 +31,18 @@
return {};
}
- if (GetParam().mRequestDP4aExtension) {
+ if (!IsD3D12()) {
+ mUseDxcEnabledOrNonD3D12 = true;
+ } else {
+ for (auto* enabledToggle : GetParam().forceEnabledWorkarounds) {
+ if (strncmp(enabledToggle, "use_dxc", 7) == 0) {
+ mUseDxcEnabledOrNonD3D12 = true;
+ break;
+ }
+ }
+ }
+
+ if (GetParam().mRequestDP4aExtension && mUseDxcEnabledOrNonD3D12) {
return {wgpu::FeatureName::ChromiumExperimentalDp4a};
}
@@ -39,9 +50,11 @@
}
bool IsDP4aSupportedOnAdapter() const { return mIsDP4aSupportedOnAdapter; }
+ bool UseDxcEnabledOrNonD3D12() const { return mUseDxcEnabledOrNonD3D12; }
private:
bool mIsDP4aSupportedOnAdapter = false;
+ bool mUseDxcEnabledOrNonD3D12 = false;
};
TEST_P(ExperimentalDP4aTests, BasicDP4aFeaturesTest) {
@@ -67,12 +80,25 @@
buf.data4 = dot4U8Packed(a, c);
}
)";
- if (!GetParam().mRequestDP4aExtension || !IsDP4aSupportedOnAdapter() ||
- (IsD3D12() && !HasToggleEnabled("use_dxc"))) {
+ const bool shouldDP4AFeatureSupportedByDevice =
+ // Required when creating device
+ GetParam().mRequestDP4aExtension &&
+ // Adapter support the feature
+ IsDP4aSupportedOnAdapter() &&
+ // Proper toggle, disallow_unsafe_apis and use_dxc if d3d12
+ // Note that "disallow_unsafe_apis" is always disabled in DawnTestBase::CreateDeviceImpl.
+ !HasToggleEnabled("disallow_unsafe_apis") && UseDxcEnabledOrNonD3D12();
+ const bool deviceSupportDP4AFeature =
+ device.HasFeature(wgpu::FeatureName::ChromiumExperimentalDp4a);
+ EXPECT_EQ(deviceSupportDP4AFeature, shouldDP4AFeatureSupportedByDevice);
+
+ if (!deviceSupportDP4AFeature) {
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, computeShader));
return;
}
+ utils::CreateShaderModule(device, computeShader);
+
wgpu::BufferDescriptor bufferDesc;
bufferDesc.size = 4 * sizeof(uint32_t);
bufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
@@ -101,6 +127,11 @@
EXPECT_BUFFER_U32_RANGE_EQ(expected, bufferOut, 0, 4);
}
+// DawnTestBase::CreateDeviceImpl always disable disallow_unsafe_apis toggle.
DAWN_INSTANTIATE_TEST_P(ExperimentalDP4aTests,
- {D3D12Backend(), D3D12Backend({"use_dxc"}), VulkanBackend()},
+ {
+ D3D12Backend(),
+ D3D12Backend({"use_dxc"}, {}),
+ VulkanBackend(),
+ },
{true, false});
diff --git a/src/dawn/tests/end2end/ShaderF16Tests.cpp b/src/dawn/tests/end2end/ShaderF16Tests.cpp
new file mode 100644
index 0000000..42c881b
--- /dev/null
+++ b/src/dawn/tests/end2end/ShaderF16Tests.cpp
@@ -0,0 +1,131 @@
+// Copyright 2022 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 <vector>
+
+#include "dawn/tests/DawnTest.h"
+#include "dawn/utils/ComboRenderPipelineDescriptor.h"
+#include "dawn/utils/WGPUHelpers.h"
+
+namespace {
+using RequireShaderF16Feature = bool;
+DAWN_TEST_PARAM_STRUCT(ShaderF16TestsParams, RequireShaderF16Feature);
+
+} // anonymous namespace
+
+class ShaderF16Tests : public DawnTestWithParams<ShaderF16TestsParams> {
+ protected:
+ std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
+ mIsShaderF16SupportedOnAdapter = SupportsFeatures({wgpu::FeatureName::ShaderF16});
+ if (!mIsShaderF16SupportedOnAdapter) {
+ return {};
+ }
+
+ if (!IsD3D12()) {
+ mUseDxcEnabledOrNonD3D12 = true;
+ } else {
+ for (auto* enabledToggle : GetParam().forceEnabledWorkarounds) {
+ if (strncmp(enabledToggle, "use_dxc", 7) == 0) {
+ mUseDxcEnabledOrNonD3D12 = true;
+ break;
+ }
+ }
+ }
+
+ if (GetParam().mRequireShaderF16Feature && mUseDxcEnabledOrNonD3D12) {
+ return {wgpu::FeatureName::ShaderF16};
+ }
+
+ return {};
+ }
+
+ bool IsShaderF16SupportedOnAdapter() const { return mIsShaderF16SupportedOnAdapter; }
+ bool UseDxcEnabledOrNonD3D12() const { return mUseDxcEnabledOrNonD3D12; }
+
+ private:
+ bool mIsShaderF16SupportedOnAdapter = false;
+ bool mUseDxcEnabledOrNonD3D12 = false;
+};
+
+TEST_P(ShaderF16Tests, BasicShaderF16FeaturesTest) {
+ const char* computeShader = R"(
+ enable f16;
+
+ struct Buf {
+ v : f32,
+ }
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(1)
+ fn CSMain() {
+ let a : f16 = f16(buf.v) + 1.0h;
+ buf.v = f32(a);
+ }
+ )";
+
+ const bool shouldShaderF16FeatureSupportedByDevice =
+ // Required when creating device
+ GetParam().mRequireShaderF16Feature &&
+ // Adapter support the feature
+ IsShaderF16SupportedOnAdapter() &&
+ // Proper toggle, disallow_unsafe_apis and use_dxc if d3d12
+ // Note that "disallow_unsafe_apis" is always disabled in DawnTestBase::CreateDeviceImpl.
+ !HasToggleEnabled("disallow_unsafe_apis") && UseDxcEnabledOrNonD3D12();
+ const bool deviceSupportShaderF16Feature = device.HasFeature(wgpu::FeatureName::ShaderF16);
+ EXPECT_EQ(deviceSupportShaderF16Feature, shouldShaderF16FeatureSupportedByDevice);
+
+ if (!deviceSupportShaderF16Feature) {
+ ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, computeShader));
+ return;
+ }
+
+ wgpu::BufferDescriptor bufferDesc;
+ bufferDesc.size = 4u;
+ bufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
+ wgpu::Buffer bufferOut = device.CreateBuffer(&bufferDesc);
+
+ wgpu::ComputePipelineDescriptor csDesc;
+ csDesc.compute.module = utils::CreateShaderModule(device, computeShader);
+ csDesc.compute.entryPoint = "CSMain";
+ wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);
+
+ wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
+ {
+ {0, bufferOut},
+ });
+
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
+ pass.SetPipeline(pipeline);
+ pass.SetBindGroup(0, bindGroup);
+ pass.DispatchWorkgroups(1);
+ pass.End();
+ wgpu::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+
+ uint32_t expected[] = {0x3f800000}; // 1.0f
+ EXPECT_BUFFER_U32_RANGE_EQ(expected, bufferOut, 0, 1);
+}
+
+// DawnTestBase::CreateDeviceImpl always disable disallow_unsafe_apis toggle.
+DAWN_INSTANTIATE_TEST_P(ShaderF16Tests,
+ {
+ D3D12Backend(),
+ D3D12Backend({"use_dxc"}),
+ VulkanBackend(),
+ MetalBackend(),
+ OpenGLBackend(),
+ OpenGLESBackend(),
+ },
+ {true, false});
diff --git a/src/dawn/tests/end2end/ShaderFloat16Tests.cpp b/src/dawn/tests/end2end/ShaderFloat16Tests.cpp
deleted file mode 100644
index 81c7ed6..0000000
--- a/src/dawn/tests/end2end/ShaderFloat16Tests.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2020 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 <vector>
-
-#include "dawn/common/Math.h"
-#include "dawn/tests/DawnTest.h"
-#include "dawn/utils/WGPUHelpers.h"
-
-class ShaderFloat16Tests : public DawnTest {
- protected:
- std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
- mIsShaderFloat16Supported = SupportsFeatures({wgpu::FeatureName::DawnShaderFloat16});
- if (!mIsShaderFloat16Supported) {
- return {};
- }
-
- return {wgpu::FeatureName::DawnShaderFloat16};
- }
-
- bool IsShaderFloat16Supported() const { return mIsShaderFloat16Supported; }
-
- bool mIsShaderFloat16Supported = false;
-};
-
-// Test basic 16bit float arithmetic and 16bit storage features.
-// TODO(crbug.com/tint/404): Implement float16 in Tint.
-TEST_P(ShaderFloat16Tests, DISABLED_Basic16BitFloatFeaturesTest) {
- DAWN_TEST_UNSUPPORTED_IF(!IsShaderFloat16Supported());
- DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsIntel()); // Flaky crashes. crbug.com/dawn/586
-
- uint16_t uniformData[] = {Float32ToFloat16(1.23), Float32ToFloat16(0.0)}; // 0.0 is a padding.
- wgpu::Buffer uniformBuffer = utils::CreateBufferFromData(
- device, &uniformData, sizeof(uniformData), wgpu::BufferUsage::Uniform);
-
- uint16_t bufferInData[] = {Float32ToFloat16(2.34), Float32ToFloat16(0.0)}; // 0.0 is a padding.
- wgpu::Buffer bufferIn = utils::CreateBufferFromData(device, &bufferInData, sizeof(bufferInData),
- wgpu::BufferUsage::Storage);
-
- wgpu::BufferDescriptor bufferDesc;
- bufferDesc.size = 2 * sizeof(uint16_t);
- bufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
- wgpu::Buffer bufferOut = device.CreateBuffer(&bufferDesc);
-
- // SPIR-V ASM produced by glslang for the following fragment shader:
- //
- // #version 450
- // #extension GL_AMD_gpu_shader_half_float : require
- //
- // struct S {
- // float16_t f;
- // float16_t padding;
- // };
- // layout(std140, set = 0, binding = 0) uniform uniformBuf { S c; };
- // layout(std140, set = 0, binding = 1) readonly buffer bufA { S a; };
- // layout(std140, set = 0, binding = 2) buffer bufB { S b; };
- //
- // void main() {
- // b.f = a.f + c.f;
- // }
-
- wgpu::ShaderModule module = utils::CreateShaderModuleFromASM(device, R"(
-; SPIR-V
-; Version: 1.0
-; Generator: Khronos Glslang Reference Front End; 10
-; Bound: 26
-; Schema: 0
- OpCapability Shader
- OpCapability Float16
- OpCapability StorageBuffer16BitAccess
- OpCapability UniformAndStorageBuffer16BitAccess
- OpExtension "SPV_KHR_16bit_storage"
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint GLCompute %main "main"
- OpExecutionMode %main LocalSize 1 1 1
- OpSource GLSL 450
- OpSourceExtension "GL_AMD_gpu_shader_half_float"
- OpName %main "main"
- OpName %S "S"
- OpMemberName %S 0 "f"
- OpMemberName %S 1 "padding"
- OpName %bufB "bufB"
- OpMemberName %bufB 0 "b"
- OpName %_ ""
- OpName %bufA "bufA"
- OpMemberName %bufA 0 "a"
- OpName %__0 ""
- OpName %uniformBuf "uniformBuf"
- OpMemberName %uniformBuf 0 "c"
- OpName %__1 ""
- OpMemberDecorate %S 0 Offset 0
- OpMemberDecorate %S 1 Offset 2
- OpMemberDecorate %bufB 0 Offset 0
- OpDecorate %bufB BufferBlock
- OpDecorate %_ DescriptorSet 0
- OpDecorate %_ Binding 2
- OpMemberDecorate %bufA 0 NonWritable
- OpMemberDecorate %bufA 0 Offset 0
- OpDecorate %bufA BufferBlock
- OpDecorate %__0 DescriptorSet 0
- OpDecorate %__0 Binding 1
- OpMemberDecorate %uniformBuf 0 Offset 0
- OpDecorate %uniformBuf Block
- OpDecorate %__1 DescriptorSet 0
- OpDecorate %__1 Binding 0
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %half = OpTypeFloat 16
- %S = OpTypeStruct %half %half
- %bufB = OpTypeStruct %S
-%_ptr_Uniform_bufB = OpTypePointer Uniform %bufB
- %_ = OpVariable %_ptr_Uniform_bufB Uniform
- %int = OpTypeInt 32 1
- %int_0 = OpConstant %int 0
- %bufA = OpTypeStruct %S
-%_ptr_Uniform_bufA = OpTypePointer Uniform %bufA
- %__0 = OpVariable %_ptr_Uniform_bufA Uniform
-%_ptr_Uniform_half = OpTypePointer Uniform %half
- %uniformBuf = OpTypeStruct %S
-%_ptr_Uniform_uniformBuf = OpTypePointer Uniform %uniformBuf
- %__1 = OpVariable %_ptr_Uniform_uniformBuf Uniform
- %main = OpFunction %void None %3
- %5 = OpLabel
- %17 = OpAccessChain %_ptr_Uniform_half %__0 %int_0 %int_0
- %18 = OpLoad %half %17
- %22 = OpAccessChain %_ptr_Uniform_half %__1 %int_0 %int_0
- %23 = OpLoad %half %22
- %24 = OpFAdd %half %18 %23
- %25 = OpAccessChain %_ptr_Uniform_half %_ %int_0 %int_0
- OpStore %25 %24
- OpReturn
- OpFunctionEnd
- )");
-
- wgpu::ComputePipelineDescriptor csDesc;
- csDesc.compute.module = module;
- csDesc.compute.entryPoint = "main";
- wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);
-
- wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
- {
- {0, uniformBuffer, 0, sizeof(uniformData)},
- {1, bufferIn, 0, sizeof(bufferInData)},
- {2, bufferOut},
- });
-
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
- pass.SetPipeline(pipeline);
- pass.SetBindGroup(0, bindGroup);
- pass.DispatchWorkgroups(1);
- pass.End();
- wgpu::CommandBuffer commands = encoder.Finish();
- queue.Submit(1, &commands);
-
- uint16_t expected[] = {Float32ToFloat16(3.57), Float32ToFloat16(0.0)}; // 0.0 is a padding.
-
- EXPECT_BUFFER_U16_RANGE_EQ(expected, bufferOut, 0, 2);
-}
-
-DAWN_INSTANTIATE_TEST(ShaderFloat16Tests,
- D3D12Backend(),
- MetalBackend(),
- OpenGLBackend(),
- OpenGLESBackend(),
- VulkanBackend());
diff --git a/src/dawn/tests/unittests/FeatureTests.cpp b/src/dawn/tests/unittests/FeatureTests.cpp
index cb7d701..b4c7fced 100644
--- a/src/dawn/tests/unittests/FeatureTests.cpp
+++ b/src/dawn/tests/unittests/FeatureTests.cpp
@@ -77,6 +77,14 @@
deviceDescriptor.requiredFeatures = &featureName;
deviceDescriptor.requiredFeaturesCount = 1;
+ // Some features may require DisallowUnsafeApis toggle disabled, otherwise CreateDevice may
+ // failed.
+ const char* const disableToggles[] = {"disallow_unsafe_apis"};
+ wgpu::DawnTogglesDeviceDescriptor toggleDesc;
+ toggleDesc.forceDisabledToggles = disableToggles;
+ toggleDesc.forceDisabledTogglesCount = 1;
+ deviceDescriptor.nextInChain = &toggleDesc;
+
dawn::native::DeviceBase* deviceBase = dawn::native::FromAPI(
adapter.CreateDevice(reinterpret_cast<const WGPUDeviceDescriptor*>(&deviceDescriptor)));
diff --git a/src/dawn/tests/unittests/native/DeviceCreationTests.cpp b/src/dawn/tests/unittests/native/DeviceCreationTests.cpp
index 09fe994..3bf15d9 100644
--- a/src/dawn/tests/unittests/native/DeviceCreationTests.cpp
+++ b/src/dawn/tests/unittests/native/DeviceCreationTests.cpp
@@ -13,6 +13,7 @@
// limitations under the License.
#include <memory>
+#include <vector>
#include "dawn/dawn_proc.h"
#include "dawn/native/DawnNative.h"
@@ -90,6 +91,42 @@
EXPECT_THAT(toggles, Contains(StrEq(toggle)));
}
+// Test features guarded by toggles are validated when creating devices.
+TEST_F(DeviceCreationTest, CreateDeviceRequiringFeaturesGuardedByToggle) {
+ std::vector<wgpu::FeatureName> featuresGuardedByToggle = {
+ wgpu::FeatureName::ShaderF16, wgpu::FeatureName::ChromiumExperimentalDp4a};
+
+ for (auto feature : featuresGuardedByToggle) {
+ wgpu::DeviceDescriptor deviceDescriptor;
+ deviceDescriptor.requiredFeatures = &feature;
+ deviceDescriptor.requiredFeaturesCount = 1;
+
+ // Test creating device without toggle would fail.
+ {
+ wgpu::Device device = adapter.CreateDevice(&deviceDescriptor);
+ EXPECT_EQ(device, nullptr);
+ }
+
+ // Test creating device without DisallowUnsafeApis toggle disabled.
+ {
+ const char* const disableToggles[] = {"disallow_unsafe_apis"};
+ wgpu::DawnTogglesDeviceDescriptor toggleDesc;
+ toggleDesc.forceDisabledToggles = disableToggles;
+ toggleDesc.forceDisabledTogglesCount = 1;
+ deviceDescriptor.nextInChain = &toggleDesc;
+
+ wgpu::Device device = adapter.CreateDevice(&deviceDescriptor);
+ EXPECT_NE(device, nullptr);
+
+ ASSERT_EQ(1u, device.EnumerateFeatures(nullptr));
+ wgpu::FeatureName enabledFeature;
+ device.EnumerateFeatures(&enabledFeature);
+ EXPECT_EQ(enabledFeature, feature);
+ device.Release();
+ }
+ }
+}
+
TEST_F(DeviceCreationTest, CreateDeviceWithCacheSuccess) {
// Default device descriptor should have the same cache key as a device descriptor with a
// default cache descriptor.
diff --git a/src/dawn/wire/SupportedFeatures.cpp b/src/dawn/wire/SupportedFeatures.cpp
index aca064f..6358405 100644
--- a/src/dawn/wire/SupportedFeatures.cpp
+++ b/src/dawn/wire/SupportedFeatures.cpp
@@ -23,6 +23,7 @@
case WGPUFeatureName_Undefined:
case WGPUFeatureName_Force32:
case WGPUFeatureName_DawnNative:
+ case WGPUFeatureName_DawnShaderFloat16: // Deprecated
return false;
case WGPUFeatureName_Depth32FloatStencil8:
case WGPUFeatureName_TimestampQuery:
@@ -32,10 +33,10 @@
case WGPUFeatureName_TextureCompressionASTC:
case WGPUFeatureName_IndirectFirstInstance:
case WGPUFeatureName_DepthClipControl:
- case WGPUFeatureName_DawnShaderFloat16:
case WGPUFeatureName_DawnInternalUsages:
case WGPUFeatureName_DawnMultiPlanarFormats:
case WGPUFeatureName_ChromiumExperimentalDp4a:
+ case WGPUFeatureName_ShaderF16:
return true;
}