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>
This commit is contained in:
Zhaoming Jiang 2022-09-08 00:11:04 +00:00 committed by Dawn LUCI CQ
parent f9eeed6106
commit 7ca82ac4d0
44 changed files with 605 additions and 333 deletions

View File

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

View File

@ -61,7 +61,15 @@ struct ToggleInfo {
// 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

View File

@ -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 @@ bool AdapterBase::GetLimits(SupportedLimits* limits) const {
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 @@ ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
DAWN_INVALID_IF(descriptor->requiredLimits->nextInChain != nullptr,
"nextInChain is not nullptr.");
}
return CreateDeviceImpl(descriptor);
return CreateDeviceImpl(descriptor, userProvidedToggles);
}
void AdapterBase::SetUseTieredLimits(bool useTieredLimits) {

View File

@ -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 @@ class AdapterBase : public RefCounted {
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 @@ class AdapterBase : public RefCounted {
virtual void InitializeVendorArchitectureImpl();
virtual MaybeError ValidateFeatureSupportedWithTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) = 0;
ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor);
virtual MaybeError ResetInternalDeviceForTestingImpl();

View File

@ -364,7 +364,7 @@ MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
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;

View File

@ -170,20 +170,19 @@ ResultOrError<Ref<PipelineLayoutBase>> ValidateLayoutAndGetRenderPipelineDescrip
// 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 @@ void DeviceBase::ApplyFeatures(const DeviceDescriptor* deviceDescriptor) {
}
}
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 @@ void DeviceBase::SetDefaultToggles() {
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,

View File

@ -62,7 +62,9 @@ using WGSLExtensionSet = std::unordered_set<std::string>;
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 @@ class DeviceBase : public RefCountedWithExternalCount {
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 @@ class DeviceBase : public RefCountedWithExternalCount {
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 @@ class DeviceBase : public RefCountedWithExternalCount {
WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata);
void ApplyToggleOverrides(const DawnTogglesDeviceDescriptor* togglesDescriptor);
void ApplyFeatures(const DeviceDescriptor* deviceDescriptor);
void SetDefaultToggles();

View File

@ -34,58 +34,64 @@ using FeatureEnumAndInfoList =
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 @@ Feature FromAPIFeature(wgpu::FeatureName feature) {
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 @@ Feature FromAPIFeature(wgpu::FeatureName feature) {
return Feature::DawnNative;
case wgpu::FeatureName::ChromiumExperimentalDp4a:
return Feature::ChromiumExperimentalDp4a;
case wgpu::FeatureName::ShaderF16:
return Feature::ShaderF16;
}
return Feature::InvalidEnum;
}
@ -135,8 +141,6 @@ wgpu::FeatureName ToAPIFeature(Feature feature) {
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 @@ wgpu::FeatureName ToAPIFeature(Feature feature) {
return wgpu::FeatureName::DawnNative;
case Feature::ChromiumExperimentalDp4a:
return wgpu::FeatureName::ChromiumExperimentalDp4a;
case Feature::ShaderF16:
return wgpu::FeatureName::ShaderF16;
case Feature::EnumCount:
break;

View File

@ -30,13 +30,13 @@ enum class Feature {
TextureCompressionBC,
TextureCompressionETC2,
TextureCompressionASTC,
ShaderFloat16,
PipelineStatisticsQuery,
TimestampQuery,
DepthClipControl,
Depth32FloatStencil8,
ChromiumExperimentalDp4a,
IndirectFirstInstance,
ShaderF16,
// Dawn-specific
DawnInternalUsages,

View File

@ -389,12 +389,12 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
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 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
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 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
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 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
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);

View File

@ -338,7 +338,7 @@ MaybeError EncodeIndirectDrawValidationCommands(DeviceBase* device,
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));

View File

@ -60,7 +60,7 @@ MaybeError ValidateQuerySetDescriptor(DeviceBase* device, const QuerySetDescript
"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 @@ MaybeError ValidateQuerySetDescriptor(DeviceBase* device, const QuerySetDescript
"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,

View File

@ -156,7 +156,7 @@ MaybeError ValidatePrimitiveState(const DeviceBase* device, const PrimitiveState
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));

View File

@ -339,7 +339,7 @@ MaybeError ValidateTextureDescriptor(const DeviceBase* device,
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;

View File

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

View File

@ -24,6 +24,8 @@
namespace dawn::native {
struct DawnTogglesDeviceDescriptor;
enum class Toggle {
EmulateStoreAndMSAAResolve,
NonzeroClearResourcesOnCreationForTesting,
@ -92,6 +94,27 @@ struct TogglesSet {
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 {

View File

@ -147,6 +147,9 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() {
dxcVersion >= MakeDXCVersion(kLeastMajorVersionForDP4a, kLeastMinorVersionForDP4a)) {
mSupportedFeatures.EnableFeature(Feature::ChromiumExperimentalDp4a);
}
if (mDeviceInfo.supportsShaderF16) {
mSupportedFeatures.EnableFeature(Feature::ShaderF16);
}
}
return {};
@ -312,6 +315,20 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
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 @@ void Adapter::CleanUpDebugLayerFilters() {
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

View File

@ -40,7 +40,9 @@ class Adapter : public AdapterBase {
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 @@ class Adapter : public AdapterBase {
MaybeError InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
MaybeError ValidateFeatureSupportedWithTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override;
MaybeError InitializeDebugLayerFilters();
void CleanUpDebugLayerFilters();

View File

@ -121,7 +121,7 @@ ResultOrError<D3D12DeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
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;

View File

@ -27,7 +27,7 @@ struct D3D12DeviceInfo {
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;

View File

@ -63,8 +63,10 @@ static constexpr uint64_t kZeroBufferSize = 1024 * 1024 * 4; // 4 Mb
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 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
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 @@ bool Device::ShouldDuplicateNumWorkgroupsForDispatchIndirect(
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());
}

View File

@ -46,7 +46,9 @@ class StagingDescriptorAllocator;
// 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 @@ class Device final : public DeviceBase {
bool ShouldDuplicateParametersForDrawIndirect(
const RenderPipelineBase* renderPipelineBase) const override;
bool IsFeatureEnabled(Feature feature) const override;
uint64_t GetBufferCopyOffsetAlignmentForDepthStencil() const override;
// Dawn APIs

View File

@ -97,7 +97,7 @@ enum class Compiler { FXC, DXC };
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 @@ ResultOrError<ComPtr<IDxcBlob>> CompileShaderDXC(const D3DBytecodeCompilationReq
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 @@ ResultOrError<CompiledShader> ShaderModule::Compile(const ProgrammableStage& pro
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)) {

View File

@ -299,8 +299,10 @@ class Adapter : public AdapterBase {
}
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 @@ class Adapter : public AdapterBase {
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
mSupportedFeatures.EnableFeature(Feature::ShaderF16);
return {};
}
@ -620,6 +624,12 @@ class Adapter : public AdapterBase {
return {};
}
MaybeError ValidateFeatureSupportedWithTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override {
return {};
}
NSPRef<id<MTLDevice>> mDevice;
};

View File

@ -38,7 +38,8 @@ class Device final : public DeviceBase {
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 @@ class Device final : public DeviceBase {
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;

View File

@ -107,16 +107,21 @@ void API_AVAILABLE(macos(10.15), ios(14)) UpdateTimestampPeriod(id<MTLDevice> de
// 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 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
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 @@ MaybeError Device::TickImpl() {
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);

View File

@ -65,8 +65,16 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
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 @@ struct CopyFromStagingToBufferOperation : PendingOperation {
// 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;
}

View File

@ -89,7 +89,9 @@ struct PendingOperation {
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 @@ class Adapter : public AdapterBase {
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,

View File

@ -141,6 +141,11 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() {
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
}
// ShaderF16
if (mFunctions.IsGLExtensionSupported("GL_AMD_gpu_shader_half_float")) {
mSupportedFeatures.EnableFeature(Feature::ShaderF16);
}
return {};
}
@ -149,12 +154,20 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
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

View File

@ -36,7 +36,13 @@ class Adapter : public AdapterBase {
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;

View File

@ -108,8 +108,10 @@ namespace dawn::native::opengl {
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 @@ ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
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();

View File

@ -43,7 +43,8 @@ class Device final : public DeviceBase {
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 @@ class Device final : public DeviceBase {
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;

View File

@ -159,6 +159,15 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() {
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 @@ bool Adapter::SupportsExternalImages() const {
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

View File

@ -46,7 +46,13 @@ class Adapter : public AdapterBase {
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;

View File

@ -78,14 +78,19 @@ class ScopedSignalSemaphore : public NonMovable {
} // 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 @@ ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalD
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 @@ ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalD
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,

View File

@ -43,7 +43,9 @@ class ResourceMemoryAllocator;
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 @@ class Device final : public DeviceBase {
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;

View File

@ -436,7 +436,7 @@ MaybeError RenderPipeline::Initialize() {
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;

View File

@ -488,7 +488,7 @@ source_set("end2end_tests_sources") {
"end2end/SamplerFilterAnisotropicTests.cpp",
"end2end/SamplerTests.cpp",
"end2end/ScissorTests.cpp",
"end2end/ShaderFloat16Tests.cpp",
"end2end/ShaderF16Tests.cpp",
"end2end/ShaderTests.cpp",
"end2end/ShaderValidationTests.cpp",
"end2end/StorageTextureTests.cpp",

View File

@ -31,7 +31,18 @@ class ExperimentalDP4aTests : public DawnTestWithParams<ExperimentalDP4aTestsPar
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 @@ class ExperimentalDP4aTests : public DawnTestWithParams<ExperimentalDP4aTestsPar
}
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 @@ TEST_P(ExperimentalDP4aTests, BasicDP4aFeaturesTest) {
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 @@ TEST_P(ExperimentalDP4aTests, BasicDP4aFeaturesTest) {
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});

View File

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

View File

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

View File

@ -77,6 +77,14 @@ TEST_F(FeatureTests, GetEnabledFeatures) {
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)));

View File

@ -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 @@ TEST_F(DeviceCreationTest, CreateDeviceWithTogglesSuccess) {
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.

View File

@ -23,6 +23,7 @@ bool IsFeatureSupported(WGPUFeatureName feature) {
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 @@ bool IsFeatureSupported(WGPUFeatureName feature) {
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;
}