// Copyright 2019 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 #include "dawn/common/Assert.h" #include "dawn/common/BitSetIterator.h" #include "dawn/native/Features.h" namespace dawn::native { namespace { struct FeatureEnumAndInfo { Feature feature; FeatureInfo info; bool WGPUDeviceProperties::*memberInWGPUDeviceProperties; }; using FeatureEnumAndInfoList = std::array(Feature::EnumCount)>; 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"}, &WGPUDeviceProperties::textureCompressionBC}, {Feature::TextureCompressionETC2, {"texture-compression-etc2", "Support Ericsson Texture Compressed (ETC2/EAC) texture " "formats", "https://bugs.chromium.org/p/dawn/issues/detail?id=955"}, &WGPUDeviceProperties::textureCompressionETC2}, {Feature::TextureCompressionASTC, {"texture-compression-astc", "Support Adaptable Scalable Texture Compressed (ASTC) " "texture formats", "https://bugs.chromium.org/p/dawn/issues/detail?id=955"}, &WGPUDeviceProperties::textureCompressionASTC}, {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"}, &WGPUDeviceProperties::shaderFloat16}, {Feature::PipelineStatisticsQuery, {"pipeline-statistics-query", "Support Pipeline Statistics Query", "https://bugs.chromium.org/p/dawn/issues/detail?id=434"}, &WGPUDeviceProperties::pipelineStatisticsQuery}, {Feature::TimestampQuery, {"timestamp-query", "Support Timestamp Query", "https://bugs.chromium.org/p/dawn/issues/detail?id=434"}, &WGPUDeviceProperties::timestampQuery}, {Feature::DepthClamping, {"depth-clamping", "Clamp depth to [0, 1] in NDC space instead of clipping", "https://bugs.chromium.org/p/dawn/issues/detail?id=716"}, &WGPUDeviceProperties::depthClamping}, {Feature::Depth24UnormStencil8, {"depth24unorm-stencil8", "Support depth24unorm-stencil8 texture format", "https://bugs.chromium.org/p/dawn/issues/detail?id=690"}, &WGPUDeviceProperties::depth24UnormStencil8}, {Feature::Depth32FloatStencil8, {"depth32float-stencil8", "Support depth32float-stencil8 texture format", "https://bugs.chromium.org/p/dawn/issues/detail?id=690"}, &WGPUDeviceProperties::depth32FloatStencil8}, {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"}, &WGPUDeviceProperties::dawnInternalUsages}, {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"}, &WGPUDeviceProperties::multiPlanarFormats}, {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"}, &WGPUDeviceProperties::dawnNative}}}; Feature FromAPIFeature(wgpu::FeatureName feature) { switch (feature) { case wgpu::FeatureName::Undefined: return Feature::InvalidEnum; case wgpu::FeatureName::TimestampQuery: return Feature::TimestampQuery; case wgpu::FeatureName::PipelineStatisticsQuery: return Feature::PipelineStatisticsQuery; case wgpu::FeatureName::TextureCompressionBC: return Feature::TextureCompressionBC; case wgpu::FeatureName::TextureCompressionETC2: return Feature::TextureCompressionETC2; case wgpu::FeatureName::TextureCompressionASTC: return Feature::TextureCompressionASTC; case wgpu::FeatureName::DepthClamping: return Feature::DepthClamping; case wgpu::FeatureName::Depth24UnormStencil8: return Feature::Depth24UnormStencil8; case wgpu::FeatureName::Depth32FloatStencil8: return Feature::Depth32FloatStencil8; case wgpu::FeatureName::DawnShaderFloat16: return Feature::ShaderFloat16; case wgpu::FeatureName::DawnInternalUsages: return Feature::DawnInternalUsages; case wgpu::FeatureName::DawnMultiPlanarFormats: return Feature::MultiPlanarFormats; case wgpu::FeatureName::DawnNative: return Feature::DawnNative; case wgpu::FeatureName::IndirectFirstInstance: return Feature::InvalidEnum; } return Feature::InvalidEnum; } wgpu::FeatureName ToAPIFeature(Feature feature) { switch (feature) { case Feature::TextureCompressionBC: return wgpu::FeatureName::TextureCompressionBC; case Feature::TextureCompressionETC2: return wgpu::FeatureName::TextureCompressionETC2; case Feature::TextureCompressionASTC: return wgpu::FeatureName::TextureCompressionASTC; case Feature::PipelineStatisticsQuery: return wgpu::FeatureName::PipelineStatisticsQuery; case Feature::TimestampQuery: return wgpu::FeatureName::TimestampQuery; case Feature::DepthClamping: return wgpu::FeatureName::DepthClamping; case Feature::Depth24UnormStencil8: return wgpu::FeatureName::Depth24UnormStencil8; case Feature::Depth32FloatStencil8: return wgpu::FeatureName::Depth32FloatStencil8; case Feature::ShaderFloat16: return wgpu::FeatureName::DawnShaderFloat16; case Feature::DawnInternalUsages: return wgpu::FeatureName::DawnInternalUsages; case Feature::MultiPlanarFormats: return wgpu::FeatureName::DawnMultiPlanarFormats; case Feature::DawnNative: return wgpu::FeatureName::DawnNative; case Feature::EnumCount: UNREACHABLE(); } } } // anonymous namespace void FeaturesSet::EnableFeature(Feature feature) { ASSERT(feature != Feature::InvalidEnum); const size_t featureIndex = static_cast(feature); featuresBitSet.set(featureIndex); } void FeaturesSet::EnableFeature(wgpu::FeatureName feature) { EnableFeature(FromAPIFeature(feature)); } bool FeaturesSet::IsEnabled(Feature feature) const { ASSERT(feature != Feature::InvalidEnum); const size_t featureIndex = static_cast(feature); return featuresBitSet[featureIndex]; } bool FeaturesSet::IsEnabled(wgpu::FeatureName feature) const { Feature f = FromAPIFeature(feature); return f != Feature::InvalidEnum && IsEnabled(f); } size_t FeaturesSet::EnumerateFeatures(wgpu::FeatureName* features) const { for (uint32_t i : IterateBitSet(featuresBitSet)) { wgpu::FeatureName feature = ToAPIFeature(static_cast(i)); if (features != nullptr) { *features = feature; features += 1; } } return featuresBitSet.count(); } std::vector FeaturesSet::GetEnabledFeatureNames() const { std::vector enabledFeatureNames(featuresBitSet.count()); uint32_t index = 0; for (uint32_t i : IterateBitSet(featuresBitSet)) { Feature feature = static_cast(i); ASSERT(feature != Feature::InvalidEnum); const FeatureEnumAndInfo& featureNameAndInfo = kFeatureNameAndInfoList[i]; ASSERT(featureNameAndInfo.feature == feature); enabledFeatureNames[index] = featureNameAndInfo.info.name; ++index; } return enabledFeatureNames; } void FeaturesSet::InitializeDeviceProperties(WGPUDeviceProperties* properties) const { ASSERT(properties != nullptr); for (uint32_t i : IterateBitSet(featuresBitSet)) { properties->*(kFeatureNameAndInfoList[i].memberInWGPUDeviceProperties) = true; } } wgpu::FeatureName FeatureEnumToAPIFeature(Feature feature) { ASSERT(feature != Feature::InvalidEnum); return ToAPIFeature(feature); } FeaturesInfo::FeaturesInfo() { for (size_t index = 0; index < kFeatureNameAndInfoList.size(); ++index) { const FeatureEnumAndInfo& featureNameAndInfo = kFeatureNameAndInfoList[index]; ASSERT(index == static_cast(featureNameAndInfo.feature)); mFeatureNameToEnumMap[featureNameAndInfo.info.name] = featureNameAndInfo.feature; } } const FeatureInfo* FeaturesInfo::GetFeatureInfo(wgpu::FeatureName feature) const { Feature f = FromAPIFeature(feature); if (f == Feature::InvalidEnum) { return nullptr; } return &kFeatureNameAndInfoList[static_cast(f)].info; } Feature FeaturesInfo::FeatureNameToEnum(const char* featureName) const { ASSERT(featureName); const auto& iter = mFeatureNameToEnumMap.find(featureName); if (iter != mFeatureNameToEnumMap.cend()) { return kFeatureNameAndInfoList[static_cast(iter->second)].feature; } // TODO(dawn:550): Remove this fallback logic when Chromium is updated. constexpr std::array, 6> kReplacementsForDeprecatedNames = {{ {"texture_compression_bc", "texture-compression-bc"}, {"depth_clamping", "depth-clamping"}, {"pipeline_statistics_query", "pipeline-statistics-query"}, {"shader_float16", "shader-float16"}, {"timestamp_query", "timestamp-query"}, {"multiplanar_formats", "multiplanar-formats"}, }}; for (const auto& [name, replacement] : kReplacementsForDeprecatedNames) { if (strcmp(featureName, name) == 0) { return FeatureNameToEnum(replacement); } } return Feature::InvalidEnum; } wgpu::FeatureName FeaturesInfo::FeatureNameToAPIEnum(const char* featureName) const { Feature f = FeatureNameToEnum(featureName); if (f != Feature::InvalidEnum) { return ToAPIFeature(f); } // Pass something invalid. return static_cast(-1); } } // namespace dawn::native