| // Copyright 2019 The Dawn & Tint Authors | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // 1. Redistributions of source code must retain the above copyright notice, this | |
| // list of conditions and the following disclaimer. | |
| // | |
| // 2. Redistributions in binary form must reproduce the above copyright notice, | |
| // this list of conditions and the following disclaimer in the documentation | |
| // and/or other materials provided with the distribution. | |
| // | |
| // 3. Neither the name of the copyright holder nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #include "src/dawn/native/Format.h" | |
| #include <bitset> | |
| #include <optional> | |
| #include <utility> | |
| #include "src/dawn/common/MatchVariant.h" | |
| #include "src/dawn/native/Device.h" | |
| #include "src/dawn/native/EnumMaskIterator.h" | |
| #include "src/dawn/native/Features.h" | |
| #include "src/dawn/native/Texture.h" | |
| #include "src/utils/typed_integer.h" | |
| namespace dawn::native { | |
| using Cap = FormatCapability; | |
| // Format | |
| SampleTypeBit SampleTypeToSampleTypeBit(wgpu::TextureSampleType sampleType) { | |
| switch (sampleType) { | |
| case wgpu::TextureSampleType::Float: | |
| case wgpu::TextureSampleType::UnfilterableFloat: | |
| case wgpu::TextureSampleType::Sint: | |
| case wgpu::TextureSampleType::Uint: | |
| case wgpu::TextureSampleType::Depth: | |
| case wgpu::TextureSampleType::BindingNotUsed: | |
| case wgpu::TextureSampleType::Undefined: | |
| // When the compiler complains that you need to add a case statement here, please | |
| // also add a corresponding static assert below! | |
| break; | |
| } | |
| static_assert(static_cast<uint32_t>(wgpu::TextureSampleType::BindingNotUsed) == 0); | |
| if (sampleType == wgpu::TextureSampleType::BindingNotUsed) { | |
| return SampleTypeBit::None; | |
| } | |
| static_assert(static_cast<uint32_t>(wgpu::TextureSampleType::Undefined) == 1); | |
| if (sampleType == wgpu::TextureSampleType::Undefined) { | |
| DAWN_UNREACHABLE(); | |
| return SampleTypeBit::None; | |
| } | |
| // Check that SampleTypeBit bits are in the same position / order as the respective | |
| // wgpu::TextureSampleType value. | |
| static_assert(SampleTypeBit::Float == | |
| static_cast<SampleTypeBit>( | |
| 1 << (static_cast<uint32_t>(wgpu::TextureSampleType::Float) - 2))); | |
| static_assert( | |
| SampleTypeBit::UnfilterableFloat == | |
| static_cast<SampleTypeBit>( | |
| 1 << (static_cast<uint32_t>(wgpu::TextureSampleType::UnfilterableFloat) - 2))); | |
| static_assert(SampleTypeBit::Uint == | |
| static_cast<SampleTypeBit>( | |
| 1 << (static_cast<uint32_t>(wgpu::TextureSampleType::Uint) - 2))); | |
| static_assert(SampleTypeBit::Sint == | |
| static_cast<SampleTypeBit>( | |
| 1 << (static_cast<uint32_t>(wgpu::TextureSampleType::Sint) - 2))); | |
| static_assert(SampleTypeBit::Depth == | |
| static_cast<SampleTypeBit>( | |
| 1 << (static_cast<uint32_t>(wgpu::TextureSampleType::Depth) - 2))); | |
| return static_cast<SampleTypeBit>(1 << (static_cast<uint32_t>(sampleType) - 2)); | |
| } | |
| const UnsupportedReason Format::supported; | |
| bool Format::IsSupported() const { | |
| return std::holds_alternative<std::monostate>(unsupportedReason); | |
| } | |
| bool Format::IsColor() const { | |
| return aspects == Aspect::Color; | |
| } | |
| bool Format::HasDepth() const { | |
| return aspects & Aspect::Depth; | |
| } | |
| bool Format::HasStencil() const { | |
| return aspects & Aspect::Stencil; | |
| } | |
| bool Format::HasDepthOrStencil() const { | |
| return aspects & (Aspect::Depth | Aspect::Stencil); | |
| } | |
| bool Format::HasAlphaChannel() const { | |
| // This is true for current formats. May need revisit if new formats and extensions are added. | |
| return componentCount == 4 && IsColor(); | |
| } | |
| bool Format::IsSnorm() const { | |
| return format == wgpu::TextureFormat::RGBA8Snorm || format == wgpu::TextureFormat::RG8Snorm || | |
| format == wgpu::TextureFormat::R8Snorm; | |
| } | |
| bool Format::IsMultiPlanar() const { | |
| return aspects & (Aspect::Plane0 | Aspect::Plane1 | Aspect::Plane2); | |
| } | |
| bool Format::CopyCompatibleWith(const Format& otherFormat) const { | |
| // TODO(crbug.com/dawn/1332): Add a Format compatibility matrix. | |
| return baseFormat == otherFormat.baseFormat; | |
| } | |
| bool Format::ViewCompatibleWith(const Format& otherFormat) const { | |
| // TODO(crbug.com/dawn/1332): Add a Format compatibility matrix. | |
| return baseFormat == otherFormat.baseFormat; | |
| } | |
| const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const { | |
| return GetAspectInfo(SelectFormatAspects(*this, aspect)); | |
| } | |
| const AspectInfo& Format::GetAspectInfo(Aspect aspect) const { | |
| DAWN_CHECK(HasOneBit(aspect)); | |
| DAWN_CHECK(aspects & aspect); | |
| const size_t aspectIndex = GetAspectIndex(aspect); | |
| DAWN_CHECK(aspectIndex < GetAspectCount(aspects)); | |
| return aspectInfo[aspectIndex]; | |
| } | |
| FormatIndex Format::GetIndex() const { | |
| return ComputeFormatIndex(format); | |
| } | |
| // FormatSet implementation | |
| bool FormatSet::operator[](const Format& format) const { | |
| return Base::operator[](format.GetIndex()); | |
| } | |
| typename std::bitset<kKnownFormatCount>::reference FormatSet::operator[](const Format& format) { | |
| return Base::operator[](format.GetIndex()); | |
| } | |
| // Implementation details of the format table of the DeviceBase | |
| // For the enum for formats are packed but this might change when we have a broader feature | |
| // mechanism for webgpu.h. Formats start at 1 because 0 is the undefined format. | |
| // Dawn internal formats start with a prefix. We strip the prefix and then pack | |
| // them after the last WebGPU format. | |
| FormatIndex ComputeFormatIndex(wgpu::TextureFormat format) { | |
| uint32_t formatValue = static_cast<uint32_t>(format); | |
| switch (formatValue & kEnumPrefixMask) { | |
| case 0: { | |
| // This takes advantage of overflows to make the index of TextureFormat::Undefined | |
| // outside of the range of the FormatTable. | |
| static_assert(static_cast<uint32_t>(wgpu::TextureFormat::Undefined) - 1 > | |
| kKnownFormatCount); | |
| uint32_t index = formatValue - 1; | |
| if (index < kWebGPUFormatCount) { | |
| return static_cast<FormatIndex>(index); | |
| } | |
| break; | |
| } | |
| case kDawnEnumPrefix: { | |
| uint32_t dawnIndex = formatValue & ~kEnumPrefixMask; | |
| if (dawnIndex < kDawnFormatCount) { | |
| return static_cast<FormatIndex>(dawnIndex + kWebGPUFormatCount); | |
| } | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| // Invalid format. Return an index outside the format table. | |
| return FormatIndex(~0u); | |
| } | |
| // Adds capabilities to color formats. | |
| void ComputeFormatCapabilities(const DeviceBase* device, FormatTable& table) { | |
| // Track the set of supported formats independently of Format::unsupportedReason because that | |
| // std::variant does not allow discriminating between "uninitialized" and "supported". | |
| ityp::bitset<FormatIndex, kKnownFormatCount> formatSupported; | |
| // Add initial capabilities to formats. | |
| auto InitialCapsAddedBy = [&](std::optional<Feature> feature, | |
| std::initializer_list<wgpu::TextureFormat> formats, Cap caps) { | |
| const bool supported = !feature.has_value() || device->HasFeature(*feature); | |
| for (wgpu::TextureFormat fmt : formats) { | |
| FormatIndex index = ComputeFormatIndex(fmt); | |
| DAWN_CHECK(index < table.size()); | |
| Format& format = table[index]; | |
| if (supported) { | |
| format.caps |= caps; // set the initial capabilities | |
| format.unsupportedReason = Format::supported; | |
| formatSupported[index] = true; | |
| } else if (!formatSupported[index] && | |
| std::holds_alternative<std::monostate>(format.unsupportedReason)) { | |
| auto requestedFeature = *feature; | |
| format.unsupportedReason = | |
| requestedFeature == Feature::CoreFeaturesAndLimits | |
| ? UnsupportedReason{CompatibilityMode{}} | |
| : UnsupportedReason{RequiresFeature{ToAPI(requestedFeature)}}; | |
| } | |
| } | |
| }; | |
| // Add caps for the supported formats | |
| auto AddCaps = [&](std::initializer_list<wgpu::TextureFormat> formats, Cap caps) { | |
| DAWN_CHECK(caps != Cap::None); | |
| for (wgpu::TextureFormat fmt : formats) { | |
| FormatIndex index = ComputeFormatIndex(fmt); | |
| DAWN_CHECK(index < table.size()); | |
| Format& format = table[index]; | |
| if (!format.IsSupported()) { | |
| continue; | |
| } | |
| format.caps |= caps; | |
| } | |
| }; | |
| // ---Initial Format capabilities without any feature --- | |
| // R8Snorm, RG8Snorm, RG11B10Ufloat, and RGB9E5Ufloat are always considered supported | |
| // even with Cap::None capabilities. | |
| InitialCapsAddedBy(std::nullopt, | |
| {wgpu::TextureFormat::R8Snorm, wgpu::TextureFormat::RG8Snorm, | |
| wgpu::TextureFormat::RG11B10Ufloat, wgpu::TextureFormat::RGB9E5Ufloat}, | |
| Cap::None); | |
| InitialCapsAddedBy(std::nullopt, | |
| {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, | |
| wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::BGRA8Unorm, | |
| wgpu::TextureFormat::R16Float, wgpu::TextureFormat::RG16Float, | |
| wgpu::TextureFormat::RGB10A2Unorm}, | |
| Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable); | |
| InitialCapsAddedBy(std::nullopt, {wgpu::TextureFormat::RGBA8Snorm}, | |
| Cap::StorageROnly | Cap::StorageWOnly); | |
| InitialCapsAddedBy(std::nullopt, {wgpu::TextureFormat::RGBA8Unorm}, | |
| Cap::StorageROnly | Cap::StorageWOnly | Cap::Renderable | Cap::Multisample | | |
| Cap::Resolve | Cap::Blendable); | |
| InitialCapsAddedBy( | |
| std::nullopt, | |
| {wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint, wgpu::TextureFormat::R16Uint, | |
| wgpu::TextureFormat::R16Sint, wgpu::TextureFormat::RG8Uint, wgpu::TextureFormat::RG8Sint, | |
| wgpu::TextureFormat::RG16Uint, wgpu::TextureFormat::RG16Sint, | |
| wgpu::TextureFormat::RGB10A2Uint}, | |
| Cap::Renderable); | |
| InitialCapsAddedBy( | |
| std::nullopt, | |
| {wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint, wgpu::TextureFormat::R32Float}, | |
| Cap::Renderable | Cap::StorageROnly | Cap::StorageWOnly | Cap::StorageRW); | |
| InitialCapsAddedBy(std::nullopt, | |
| {wgpu::TextureFormat::RGBA8Uint, wgpu::TextureFormat::RGBA8Sint}, | |
| Cap::Renderable | Cap::StorageROnly | Cap::StorageWOnly); | |
| InitialCapsAddedBy(std::nullopt, | |
| {wgpu::TextureFormat::RG32Uint, wgpu::TextureFormat::RG32Sint, | |
| wgpu::TextureFormat::RG32Float}, | |
| Cap::Renderable); | |
| InitialCapsAddedBy(std::nullopt, | |
| {wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::RGBA16Sint}, | |
| Cap::Renderable | Cap::StorageROnly | Cap::StorageWOnly); | |
| InitialCapsAddedBy( | |
| std::nullopt, {wgpu::TextureFormat::RGBA16Float}, | |
| Cap::Renderable | Cap::StorageROnly | Cap::StorageWOnly | Cap::Resolve | Cap::Blendable); | |
| InitialCapsAddedBy(std::nullopt, | |
| {wgpu::TextureFormat::RGBA32Uint, wgpu::TextureFormat::RGBA32Sint, | |
| wgpu::TextureFormat::RGBA32Float}, | |
| Cap::Renderable | Cap::StorageROnly | Cap::StorageWOnly); | |
| // Initialize the format capabilities and add the pre-initialized format capabilities when | |
| // relevant features are enabled | |
| // The two YCbCr extensions each add support for OpaqueYCbCrAndroid. | |
| InitialCapsAddedBy(Feature::YCbCrVulkanSamplers, {wgpu::TextureFormat::OpaqueYCbCrAndroid}, | |
| Cap::None); | |
| InitialCapsAddedBy(Feature::OpaqueYCbCrAndroidForExternalTexture, | |
| {wgpu::TextureFormat::OpaqueYCbCrAndroid}, Cap::None); | |
| InitialCapsAddedBy(Feature::CoreFeaturesAndLimits, {wgpu::TextureFormat::BGRA8UnormSrgb}, | |
| Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable); | |
| if (device->HasFeature(Feature::CoreFeaturesAndLimits)) { | |
| AddCaps( | |
| {wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint, wgpu::TextureFormat::R16Uint, | |
| wgpu::TextureFormat::R16Sint, wgpu::TextureFormat::RG8Uint, | |
| wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::RG16Uint, | |
| wgpu::TextureFormat::RG16Sint, wgpu::TextureFormat::RGB10A2Uint, | |
| wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RGBA8Uint, | |
| wgpu::TextureFormat::RGBA8Sint, wgpu::TextureFormat::RGBA16Float, | |
| wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::RGBA16Sint}, | |
| Cap::Multisample); | |
| AddCaps({wgpu::TextureFormat::RG32Uint, wgpu::TextureFormat::RG32Sint, | |
| wgpu::TextureFormat::RG32Float}, | |
| Cap::StorageROnly | Cap::StorageWOnly); | |
| } | |
| if (device->HasFeature(Feature::PixelLocalStorageCoherent) || | |
| device->HasFeature(Feature::PixelLocalStorageNonCoherent)) { | |
| AddCaps({wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint, | |
| wgpu::TextureFormat::R32Float}, | |
| Cap::PLS); | |
| } | |
| if (device->HasFeature(Feature::Float32Blendable)) { | |
| AddCaps({wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RG32Float, | |
| wgpu::TextureFormat::RGBA32Float}, | |
| Cap::Blendable); | |
| } | |
| InitialCapsAddedBy(Feature::TextureFormatsTier1, | |
| {wgpu::TextureFormat::R16Unorm, wgpu::TextureFormat::RG16Unorm, | |
| wgpu::TextureFormat::RGBA16Unorm, wgpu::TextureFormat::R16Snorm, | |
| wgpu::TextureFormat::RG16Snorm, wgpu::TextureFormat::RGBA16Snorm}, | |
| Cap::Renderable | Cap::Multisample | Cap::Blendable | Cap::StorageROnly | | |
| Cap::StorageWOnly); | |
| if (device->HasFeature(Feature::TextureFormatsTier1)) { | |
| AddCaps({wgpu::TextureFormat::R8Snorm, wgpu::TextureFormat::RG8Snorm, | |
| wgpu::TextureFormat::RGBA8Snorm}, | |
| Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable); | |
| AddCaps( | |
| { | |
| wgpu::TextureFormat::R8Unorm, | |
| wgpu::TextureFormat::R8Snorm, | |
| wgpu::TextureFormat::R8Uint, | |
| wgpu::TextureFormat::R8Sint, | |
| wgpu::TextureFormat::RG8Unorm, | |
| wgpu::TextureFormat::RG8Snorm, | |
| wgpu::TextureFormat::RG8Uint, | |
| wgpu::TextureFormat::RG8Sint, | |
| wgpu::TextureFormat::R16Uint, | |
| wgpu::TextureFormat::R16Sint, | |
| wgpu::TextureFormat::R16Float, | |
| wgpu::TextureFormat::RG16Uint, | |
| wgpu::TextureFormat::RG16Sint, | |
| wgpu::TextureFormat::RG16Float, | |
| wgpu::TextureFormat::RGB10A2Uint, | |
| wgpu::TextureFormat::RGB10A2Unorm, | |
| wgpu::TextureFormat::RG11B10Ufloat, | |
| }, | |
| Cap::StorageROnly | Cap::StorageWOnly); | |
| } | |
| if (device->HasFeature(Feature::TextureFormatsTier2)) { | |
| AddCaps( | |
| {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint, | |
| wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::R16Sint, | |
| wgpu::TextureFormat::R16Float, wgpu::TextureFormat::RGBA8Unorm, | |
| wgpu::TextureFormat::RGBA8Uint, wgpu::TextureFormat::RGBA8Sint, | |
| wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::RGBA16Sint, | |
| wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Uint, | |
| wgpu::TextureFormat::RGBA32Sint, wgpu::TextureFormat::RGBA32Float}, | |
| Cap::StorageRW); | |
| } | |
| if (device->HasFeature(Feature::BGRA8UnormStorage)) { | |
| AddCaps({wgpu::TextureFormat::BGRA8Unorm}, Cap::StorageWOnly); | |
| } | |
| if (device->HasFeature(Feature::RG11B10UfloatRenderable)) { | |
| AddCaps({wgpu::TextureFormat::RG11B10Ufloat}, | |
| Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable); | |
| } | |
| InitialCapsAddedBy(Feature::Unorm16TextureFormats, | |
| {wgpu::TextureFormat::R16Unorm, wgpu::TextureFormat::RG16Unorm, | |
| wgpu::TextureFormat::RGBA16Unorm}, | |
| Cap::Renderable | Cap::Multisample | Cap::Resolve); | |
| } | |
| FormatTable BuildFormatTable(const DeviceBase* device) { | |
| FormatTable table; | |
| FormatSet formatsSet; | |
| static constexpr SampleTypeBit kAnyFloat = | |
| SampleTypeBit::Float | SampleTypeBit::UnfilterableFloat; | |
| auto AddFormat = [&table, &formatsSet](Format format) { | |
| FormatIndex index = ComputeFormatIndex(format.format); | |
| DAWN_CHECK(index < table.size()); | |
| // This checks that each format is set at most once, the first part of checking that all | |
| // formats are set exactly once. | |
| DAWN_CHECK(!formatsSet[index]); | |
| // Vulkan describes bytesPerRow in units of texels. If there's any format for which this | |
| // DAWN_CHECK isn't true, then additional validation on bytesPerRow must be added. | |
| const bool hasMultipleAspects = !HasOneBit(format.aspects); | |
| DAWN_CHECK(hasMultipleAspects || | |
| (kTextureBytesPerRowAlignment % format.aspectInfo[0].block.byteSize) == 0); | |
| table[index] = format; | |
| formatsSet.set(index); | |
| }; | |
| using Width = TypedInteger<struct WidthT, uint32_t>; | |
| using Height = TypedInteger<struct HeightT, uint32_t>; | |
| using ByteSize = TypedInteger<struct ByteSizeT, uint32_t>; | |
| using RenderTargetPixelByteCost = TypedInteger<struct RenderTargetPixelByteCostT, uint32_t>; | |
| using ComponentCount = TypedInteger<struct ComponentCountT, uint32_t>; | |
| using RenderTargetComponentAlignment = | |
| TypedInteger<struct RenderTargetComponentAlignmentT, uint32_t>; | |
| auto DefineColorFormat = | |
| [&](wgpu::TextureFormat fmt, ByteSize byteSize, SampleTypeBit sampleTypes, | |
| ComponentCount componentCount, | |
| RenderTargetPixelByteCost rtPixelCost = RenderTargetPixelByteCost(0u), | |
| RenderTargetComponentAlignment rtComponentAlign = RenderTargetComponentAlignment(0u), | |
| wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) { | |
| Format internalFormat; | |
| internalFormat.format = fmt; | |
| internalFormat.baseFormat = | |
| (baseFormat == wgpu::TextureFormat::Undefined) ? fmt : baseFormat; | |
| internalFormat.isCompressed = false; | |
| internalFormat.aspects = Aspect::Color; | |
| internalFormat.componentCount = static_cast<uint32_t>(componentCount); | |
| internalFormat.unsupportedReason = std::monostate{}; | |
| internalFormat.caps = Cap::None; | |
| if (rtPixelCost != RenderTargetPixelByteCost(0u)) { | |
| internalFormat.renderTargetPixelByteCost = static_cast<uint32_t>(rtPixelCost); | |
| internalFormat.renderTargetComponentAlignment = | |
| static_cast<uint32_t>(rtComponentAlign); | |
| } | |
| AspectInfo* aspect = internalFormat.aspectInfo.data(); | |
| aspect->block.byteSize = static_cast<uint32_t>(byteSize); | |
| aspect->block.width = 1; | |
| aspect->block.height = 1; | |
| aspect->supportedSampleTypes = sampleTypes; | |
| aspect->format = fmt; | |
| if (HasOneBit(sampleTypes)) { | |
| switch (sampleTypes) { | |
| case SampleTypeBit::Float: | |
| case SampleTypeBit::UnfilterableFloat: | |
| aspect->baseType = TextureComponentType::Float; | |
| break; | |
| case SampleTypeBit::Sint: | |
| aspect->baseType = TextureComponentType::Sint; | |
| break; | |
| case SampleTypeBit::Uint: | |
| aspect->baseType = TextureComponentType::Uint; | |
| break; | |
| default: | |
| DAWN_UNREACHABLE(); | |
| } | |
| } else { | |
| aspect->baseType = TextureComponentType::Float; | |
| } | |
| AddFormat(internalFormat); | |
| }; | |
| SampleTypeBit sampleTypeFor32BitFloatFormats = device->HasFeature(Feature::Float32Filterable) | |
| ? kAnyFloat | |
| : SampleTypeBit::UnfilterableFloat; | |
| SampleTypeBit sampleTypeForNorm16Formats = | |
| (device->HasFeature(Feature::Unorm16TextureFormats) || | |
| device->HasFeature(Feature::Unorm16Filterable)) | |
| ? kAnyFloat | |
| : SampleTypeBit::UnfilterableFloat; | |
| // 1 byte | |
| DefineColorFormat(wgpu::TextureFormat::R8Unorm, ByteSize(1u), kAnyFloat, ComponentCount(1u), | |
| RenderTargetPixelByteCost(1u), RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::R8Snorm, ByteSize(1u), kAnyFloat, ComponentCount(1u), | |
| RenderTargetPixelByteCost(1u), RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::R8Uint, ByteSize(1u), SampleTypeBit::Uint, | |
| ComponentCount(1u), RenderTargetPixelByteCost(1u), | |
| RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::R8Sint, ByteSize(1u), SampleTypeBit::Sint, | |
| ComponentCount(1u), RenderTargetPixelByteCost(1u), | |
| RenderTargetComponentAlignment(1u)); | |
| // 2 bytes | |
| DefineColorFormat(wgpu::TextureFormat::R16Uint, ByteSize(2u), SampleTypeBit::Uint, | |
| ComponentCount(1u), RenderTargetPixelByteCost(2u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::R16Sint, ByteSize(2u), SampleTypeBit::Sint, | |
| ComponentCount(1u), RenderTargetPixelByteCost(2u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::R16Float, ByteSize(2u), kAnyFloat, ComponentCount(1u), | |
| RenderTargetPixelByteCost(2u), RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG8Unorm, ByteSize(2u), kAnyFloat, ComponentCount(2u), | |
| RenderTargetPixelByteCost(2u), RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG8Snorm, ByteSize(2u), kAnyFloat, ComponentCount(2u), | |
| RenderTargetPixelByteCost(2u), RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG8Uint, ByteSize(2u), SampleTypeBit::Uint, | |
| ComponentCount(2u), RenderTargetPixelByteCost(2u), | |
| RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG8Sint, ByteSize(2u), SampleTypeBit::Sint, | |
| ComponentCount(2u), RenderTargetPixelByteCost(2u), | |
| RenderTargetComponentAlignment(1u)); | |
| // 4 bytes | |
| DefineColorFormat(wgpu::TextureFormat::R32Uint, ByteSize(4u), SampleTypeBit::Uint, | |
| ComponentCount(1u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::R32Sint, ByteSize(4u), SampleTypeBit::Sint, | |
| ComponentCount(1u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::R32Float, ByteSize(4u), sampleTypeFor32BitFloatFormats, | |
| ComponentCount(1u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG16Uint, ByteSize(4u), SampleTypeBit::Uint, | |
| ComponentCount(2u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG16Sint, ByteSize(4u), SampleTypeBit::Sint, | |
| ComponentCount(2u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG16Float, ByteSize(4u), kAnyFloat, ComponentCount(2u), | |
| RenderTargetPixelByteCost(4u), RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA8Unorm, ByteSize(4u), kAnyFloat, ComponentCount(4u), | |
| RenderTargetPixelByteCost(8u), RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, ByteSize(4u), kAnyFloat, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(1u), wgpu::TextureFormat::RGBA8Unorm); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA8Snorm, ByteSize(4u), kAnyFloat, ComponentCount(4u), | |
| RenderTargetPixelByteCost(4u), RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA8Uint, ByteSize(4u), SampleTypeBit::Uint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA8Sint, ByteSize(4u), SampleTypeBit::Sint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::BGRA8Unorm, ByteSize(4u), kAnyFloat, ComponentCount(4u), | |
| RenderTargetPixelByteCost(8u), RenderTargetComponentAlignment(1u)); | |
| DefineColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, ByteSize(4u), kAnyFloat, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(1u), wgpu::TextureFormat::BGRA8Unorm); | |
| DefineColorFormat(wgpu::TextureFormat::RGB10A2Uint, ByteSize(4u), SampleTypeBit::Uint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGB10A2Unorm, ByteSize(4u), kAnyFloat, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG11B10Ufloat, ByteSize(4u), kAnyFloat, | |
| ComponentCount(3u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, ByteSize(4u), kAnyFloat, | |
| ComponentCount(3u)); | |
| // The OpaqueYCbCrAndroid format acts as if it is a float format, but we later validate when it | |
| // is used with a static sampler that the sampler's filteringness matches what the YCbCr info | |
| // allows. | |
| DefineColorFormat(wgpu::TextureFormat::OpaqueYCbCrAndroid, ByteSize(1u), kAnyFloat, | |
| ComponentCount(0u)); | |
| // 8 bytes | |
| DefineColorFormat(wgpu::TextureFormat::RG32Uint, ByteSize(8u), SampleTypeBit::Uint, | |
| ComponentCount(2u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG32Sint, ByteSize(8u), SampleTypeBit::Sint, | |
| ComponentCount(2u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG32Float, ByteSize(8u), sampleTypeFor32BitFloatFormats, | |
| ComponentCount(2u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA16Uint, ByteSize(8u), SampleTypeBit::Uint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA16Sint, ByteSize(8u), SampleTypeBit::Sint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA16Float, ByteSize(8u), kAnyFloat, ComponentCount(4u), | |
| RenderTargetPixelByteCost(8u), RenderTargetComponentAlignment(2u)); | |
| // 16 bytes | |
| DefineColorFormat(wgpu::TextureFormat::RGBA32Uint, ByteSize(16u), SampleTypeBit::Uint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(16u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA32Sint, ByteSize(16u), SampleTypeBit::Sint, | |
| ComponentCount(4u), RenderTargetPixelByteCost(16u), | |
| RenderTargetComponentAlignment(4u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA32Float, ByteSize(16u), | |
| sampleTypeFor32BitFloatFormats, ComponentCount(4u), | |
| RenderTargetPixelByteCost(16u), RenderTargetComponentAlignment(4u)); | |
| // Norm16 | |
| DefineColorFormat(wgpu::TextureFormat::R16Unorm, ByteSize(2u), sampleTypeForNorm16Formats, | |
| ComponentCount(1u), RenderTargetPixelByteCost(2u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG16Unorm, ByteSize(4u), sampleTypeForNorm16Formats, | |
| ComponentCount(2u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA16Unorm, ByteSize(8u), sampleTypeForNorm16Formats, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::R16Snorm, ByteSize(2u), sampleTypeForNorm16Formats, | |
| ComponentCount(1u), RenderTargetPixelByteCost(2u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RG16Snorm, ByteSize(4u), sampleTypeForNorm16Formats, | |
| ComponentCount(2u), RenderTargetPixelByteCost(4u), | |
| RenderTargetComponentAlignment(2u)); | |
| DefineColorFormat(wgpu::TextureFormat::RGBA16Snorm, ByteSize(8u), sampleTypeForNorm16Formats, | |
| ComponentCount(4u), RenderTargetPixelByteCost(8u), | |
| RenderTargetComponentAlignment(2u)); | |
| ComputeFormatCapabilities(device, table); | |
| auto AddDepthFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize, | |
| UnsupportedReason unsupportedReason) { | |
| Format internalFormat; | |
| internalFormat.format = format; | |
| internalFormat.baseFormat = format; | |
| internalFormat.isCompressed = false; | |
| internalFormat.unsupportedReason = unsupportedReason; | |
| internalFormat.aspects = Aspect::Depth; | |
| internalFormat.componentCount = 1; | |
| internalFormat.caps = Cap::Renderable | Cap::Multisample; | |
| AspectInfo* firstAspect = internalFormat.aspectInfo.data(); | |
| firstAspect->block.byteSize = byteSize; | |
| firstAspect->block.width = 1; | |
| firstAspect->block.height = 1; | |
| firstAspect->baseType = TextureComponentType::Float; | |
| firstAspect->supportedSampleTypes = SampleTypeBit::Depth | SampleTypeBit::UnfilterableFloat; | |
| firstAspect->format = format; | |
| AddFormat(internalFormat); | |
| }; | |
| auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format, | |
| UnsupportedReason unsupportedReason) { | |
| Format internalFormat; | |
| internalFormat.format = format; | |
| internalFormat.baseFormat = format; | |
| internalFormat.isCompressed = false; | |
| internalFormat.unsupportedReason = unsupportedReason; | |
| internalFormat.caps = Cap::Renderable | Cap::Multisample; | |
| internalFormat.aspects = Aspect::Stencil; | |
| internalFormat.componentCount = 1; | |
| // Duplicate the data for the stencil aspect in both the first and second aspect info. | |
| // - aspectInfo[0] is used by AddMultiAspectFormat to copy the info for the whole | |
| // stencil8 aspect of depth-stencil8 formats. | |
| // - aspectInfo[1] is the actual info used in the rest of Dawn since | |
| // GetAspectIndex(Aspect::Stencil) is 1. | |
| DAWN_CHECK(GetAspectIndex(Aspect::Stencil) == 1); | |
| internalFormat.aspectInfo[0].block.byteSize = 1; | |
| internalFormat.aspectInfo[0].block.width = 1; | |
| internalFormat.aspectInfo[0].block.height = 1; | |
| internalFormat.aspectInfo[0].baseType = TextureComponentType::Uint; | |
| internalFormat.aspectInfo[0].supportedSampleTypes = SampleTypeBit::Uint; | |
| internalFormat.aspectInfo[0].format = format; | |
| internalFormat.aspectInfo[1] = internalFormat.aspectInfo[0]; | |
| AddFormat(internalFormat); | |
| }; | |
| auto BaseCompressedFormat = [](wgpu::TextureFormat format, ByteSize byteSize, Width width, | |
| Height height, UnsupportedReason unsupportedReason, | |
| ComponentCount componentCount, wgpu::TextureFormat baseFormat) { | |
| Format internalFormat; | |
| internalFormat.format = format; | |
| internalFormat.isCompressed = true; | |
| internalFormat.unsupportedReason = unsupportedReason; | |
| internalFormat.aspects = Aspect::Color; | |
| internalFormat.componentCount = static_cast<uint32_t>(componentCount); | |
| // Default baseFormat of each compressed formats should be themselves. | |
| if (baseFormat == wgpu::TextureFormat::Undefined) { | |
| internalFormat.baseFormat = format; | |
| } else { | |
| internalFormat.baseFormat = baseFormat; | |
| } | |
| AspectInfo* firstAspect = internalFormat.aspectInfo.data(); | |
| firstAspect->block.byteSize = static_cast<uint32_t>(byteSize); | |
| firstAspect->block.width = static_cast<uint32_t>(width); | |
| firstAspect->block.height = static_cast<uint32_t>(height); | |
| firstAspect->baseType = TextureComponentType::Float; | |
| firstAspect->supportedSampleTypes = kAnyFloat; | |
| firstAspect->format = format; | |
| return internalFormat; | |
| }; | |
| auto AddETCCompressedFormat = | |
| [&BaseCompressedFormat, &AddFormat]( | |
| wgpu::TextureFormat format, ByteSize byteSize, Width width, Height height, | |
| UnsupportedReason unsupportedReason, ComponentCount componentCount, | |
| wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) { | |
| Format internalFormat = BaseCompressedFormat( | |
| format, byteSize, width, height, unsupportedReason, componentCount, baseFormat); | |
| AddFormat(internalFormat); | |
| }; | |
| auto AddBCCompressedFormat = | |
| [&BaseCompressedFormat, &AddFormat]( | |
| wgpu::TextureFormat format, ByteSize byteSize, Width width, Height height, | |
| UnsupportedReason unsupportedReason, ComponentCount componentCount, | |
| wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) { | |
| Format internalFormat = BaseCompressedFormat( | |
| format, byteSize, width, height, unsupportedReason, componentCount, baseFormat); | |
| internalFormat.isBC = true; | |
| AddFormat(internalFormat); | |
| }; | |
| auto AddASTCCompressedFormat = | |
| [&BaseCompressedFormat, &AddFormat]( | |
| wgpu::TextureFormat format, ByteSize byteSize, Width width, Height height, | |
| UnsupportedReason unsupportedReason, ComponentCount componentCount, | |
| wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) { | |
| Format internalFormat = BaseCompressedFormat( | |
| format, byteSize, width, height, unsupportedReason, componentCount, baseFormat); | |
| internalFormat.isASTC = true; | |
| AddFormat(internalFormat); | |
| }; | |
| auto AddMultiAspectFormat = | |
| [&AddFormat, &table](wgpu::TextureFormat format, TextureSubsampling subSampling, | |
| Aspect aspects, Cap capabilites, UnsupportedReason unsupportedReason, | |
| ComponentCount componentCount, wgpu::TextureFormat firstFormat, | |
| wgpu::TextureFormat secondFormat, | |
| wgpu::TextureFormat thirdFormat = wgpu::TextureFormat::Undefined) { | |
| Format internalFormat; | |
| internalFormat.format = format; | |
| internalFormat.baseFormat = format; | |
| internalFormat.subSampling = subSampling; | |
| internalFormat.isCompressed = false; | |
| internalFormat.unsupportedReason = unsupportedReason; | |
| internalFormat.caps = capabilites; | |
| internalFormat.aspects = aspects; | |
| internalFormat.componentCount = static_cast<uint32_t>(componentCount); | |
| // Multi aspect formats just copy information about single-aspect formats. This | |
| // means that the single-plane formats must have been added before multi-aspect | |
| // ones. (it is ASSERTed below). | |
| const FormatIndex firstFormatIndex = ComputeFormatIndex(firstFormat); | |
| const FormatIndex secondFormatIndex = ComputeFormatIndex(secondFormat); | |
| DAWN_CHECK(table[firstFormatIndex].aspectInfo[0].format != | |
| wgpu::TextureFormat::Undefined); | |
| DAWN_CHECK(table[secondFormatIndex].aspectInfo[0].format != | |
| wgpu::TextureFormat::Undefined); | |
| internalFormat.aspectInfo[0] = table[firstFormatIndex].aspectInfo[0]; | |
| internalFormat.aspectInfo[1] = table[secondFormatIndex].aspectInfo[0]; | |
| if (thirdFormat != wgpu::TextureFormat::Undefined) { | |
| const FormatIndex thirdFormatIndex = ComputeFormatIndex(thirdFormat); | |
| internalFormat.aspectInfo[2] = table[thirdFormatIndex].aspectInfo[0]; | |
| } | |
| AddFormat(internalFormat); | |
| }; | |
| // clang-format off | |
| // Depth-stencil formats | |
| AddStencilFormat(wgpu::TextureFormat::Stencil8, Format::supported); | |
| AddDepthFormat(wgpu::TextureFormat::Depth16Unorm, 2, Format::supported); | |
| // TODO(crbug.com/dawn/843): This is 4 because we read this to perform zero initialization, | |
| // and textures are always use depth32float. We should improve this to be more robust. Perhaps, | |
| // using 0 here to mean "unsized" and adding a backend-specific query for the block size. | |
| AddDepthFormat(wgpu::TextureFormat::Depth24Plus, 4, Format::supported); | |
| AddMultiAspectFormat(wgpu::TextureFormat::Depth24PlusStencil8, TextureSubsampling::Undefined, | |
| Aspect::Depth | Aspect::Stencil, Cap::Renderable | Cap::Multisample, Format::supported, ComponentCount(2u), wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8); | |
| AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4, Format::supported); | |
| UnsupportedReason d32s8UnsupportedReason = device->HasFeature(Feature::Depth32FloatStencil8) ? Format::supported : RequiresFeature{wgpu::FeatureName::Depth32FloatStencil8}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::Depth32FloatStencil8, TextureSubsampling::Undefined, | |
| Aspect::Depth | Aspect::Stencil, Cap::Renderable | Cap::Multisample, d32s8UnsupportedReason, ComponentCount(2u), wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Stencil8); | |
| // BC compressed formats | |
| UnsupportedReason bcFormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionBC) ? Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionBC}; | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, ByteSize(8u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, ByteSize(8u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::BC1RGBAUnorm); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC4RSnorm, ByteSize(8u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(1u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC4RUnorm, ByteSize(8u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(1u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::BC2RGBAUnorm); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::BC3RGBAUnorm); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(2u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(2u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(3u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(3u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddBCCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, ByteSize(16u), Width(4u), Height(4u), bcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::BC7RGBAUnorm); | |
| // ETC2/EAC compressed formats | |
| UnsupportedReason etc2FormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionETC2) ? Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionETC2}; | |
| AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, ByteSize(8u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(3u)); | |
| AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, ByteSize(8u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::ETC2RGB8Unorm); | |
| AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, ByteSize(8u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(4u)); | |
| AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, ByteSize(8u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ETC2RGB8A1Unorm); | |
| AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, ByteSize(16u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(4u)); | |
| AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, ByteSize(16u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ETC2RGBA8Unorm); | |
| AddETCCompressedFormat(wgpu::TextureFormat::EACR11Unorm, ByteSize(8u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(1u)); | |
| AddETCCompressedFormat(wgpu::TextureFormat::EACR11Snorm, ByteSize(8u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(1u)); | |
| AddETCCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, ByteSize(16u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(2u)); | |
| AddETCCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, ByteSize(16u), Width(4u), Height(4u), etc2FormatUnsupportedReason, ComponentCount(2u)); | |
| // ASTC compressed formats | |
| UnsupportedReason astcFormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionASTC) ? Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionASTC}; | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, ByteSize(16u), Width(4u), Height(4u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, ByteSize(16u), Width(4u), Height(4u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC4x4Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, ByteSize(16u), Width(5u), Height(4u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, ByteSize(16u), Width(5u), Height(4u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC5x4Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, ByteSize(16u), Width(5u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, ByteSize(16u), Width(5u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC5x5Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, ByteSize(16u), Width(6u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, ByteSize(16u), Width(6u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC6x5Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, ByteSize(16u), Width(6u), Height(6u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, ByteSize(16u), Width(6u), Height(6u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC6x6Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, ByteSize(16u), Width(8u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, ByteSize(16u), Width(8u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC8x5Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, ByteSize(16u), Width(8u), Height(6u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, ByteSize(16u), Width(8u), Height(6u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC8x6Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, ByteSize(16u), Width(8u), Height(8u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, ByteSize(16u), Width(8u), Height(8u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC8x8Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, ByteSize(16u), Width(10u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, ByteSize(16u), Width(10u), Height(5u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC10x5Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, ByteSize(16u), Width(10u), Height(6u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, ByteSize(16u), Width(10u), Height(6u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC10x6Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, ByteSize(16u), Width(10u), Height(8u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, ByteSize(16u), Width(10u), Height(8u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC10x8Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, ByteSize(16u), Width(10u), Height(10u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, ByteSize(16u), Width(10u), Height(10u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC10x10Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, ByteSize(16u), Width(12u), Height(10u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, ByteSize(16u), Width(12u), Height(10u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC12x10Unorm); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, ByteSize(16u), Width(12u), Height(12u), astcFormatUnsupportedReason, ComponentCount(4u)); | |
| AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, ByteSize(16u), Width(12u), Height(12u), astcFormatUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::ASTC12x12Unorm); | |
| // multi-planar formats | |
| auto multiPlanarCapabilities = device->HasFeature(Feature::MultiPlanarRenderTargets) ? Cap::Renderable : Cap::None; | |
| const UnsupportedReason multiPlanarFormatNv12UnsupportedReason = device->HasFeature(Feature::DawnMultiPlanarFormats) ? Format::supported : RequiresFeature{wgpu::FeatureName::DawnMultiPlanarFormats}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, TextureSubsampling::e420, Aspect::Plane0 | Aspect::Plane1, | |
| multiPlanarCapabilities, multiPlanarFormatNv12UnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm); | |
| const UnsupportedReason multiPlanarFormatNv16UnsupportedReason = device->HasFeature(Feature::MultiPlanarFormatNv16) ? Format::supported : RequiresFeature{wgpu::FeatureName::MultiPlanarFormatNv16}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar422Unorm, TextureSubsampling::e422, Aspect::Plane0 | Aspect::Plane1, | |
| multiPlanarCapabilities, multiPlanarFormatNv16UnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm); | |
| const UnsupportedReason multiPlanarFormatNv24UnsupportedReason = device->HasFeature(Feature::MultiPlanarFormatNv24) ? Format::supported : RequiresFeature{wgpu::FeatureName::MultiPlanarFormatNv24}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar444Unorm, TextureSubsampling::e444, Aspect::Plane0 | Aspect::Plane1, | |
| multiPlanarCapabilities, multiPlanarFormatNv24UnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm); | |
| const UnsupportedReason multiPlanarFormatP010UnsupportedReason = device->HasFeature(Feature::MultiPlanarFormatP010) ? Format::supported : RequiresFeature{wgpu::FeatureName::MultiPlanarFormatP010}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm, TextureSubsampling::e420, Aspect::Plane0 | Aspect::Plane1, | |
| multiPlanarCapabilities, multiPlanarFormatP010UnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::R16Unorm, wgpu::TextureFormat::RG16Unorm); | |
| const UnsupportedReason multiPlanarFormatP210UnsupportedReason = device->HasFeature(Feature::MultiPlanarFormatP210) ? Format::supported : RequiresFeature{wgpu::FeatureName::MultiPlanarFormatP210}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R10X6BG10X6Biplanar422Unorm, TextureSubsampling::e422, Aspect::Plane0 | Aspect::Plane1, | |
| multiPlanarCapabilities, multiPlanarFormatP210UnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::R16Unorm, wgpu::TextureFormat::RG16Unorm); | |
| const UnsupportedReason multiPlanarFormatP410UnsupportedReason = device->HasFeature(Feature::MultiPlanarFormatP410) ? Format::supported : RequiresFeature{wgpu::FeatureName::MultiPlanarFormatP410}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R10X6BG10X6Biplanar444Unorm, TextureSubsampling::e444, Aspect::Plane0 | Aspect::Plane1, | |
| multiPlanarCapabilities, multiPlanarFormatP410UnsupportedReason, ComponentCount(3u), wgpu::TextureFormat::R16Unorm, wgpu::TextureFormat::RG16Unorm); | |
| const UnsupportedReason multiPlanarFormatNv12aUnsupportedReason = device->HasFeature(Feature::MultiPlanarFormatNv12a) ? Format::supported : RequiresFeature{wgpu::FeatureName::MultiPlanarFormatNv12a}; | |
| AddMultiAspectFormat(wgpu::TextureFormat::R8BG8A8Triplanar420Unorm, TextureSubsampling::e420, Aspect::Plane0 | Aspect::Plane1 | Aspect::Plane2, | |
| multiPlanarCapabilities, multiPlanarFormatNv12aUnsupportedReason, ComponentCount(4u), wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::R8Unorm); | |
| // clang-format on | |
| // This checks that each format is set at least once, the second part of checking that all | |
| // formats are checked exactly once. If this assertion is failing and texture formats have | |
| // been added or removed recently, check that kKnownFormatCount has been updated. | |
| DAWN_CHECK(formatsSet.all()); | |
| for (const Format& f : table) { | |
| if (f.format != f.baseFormat) { | |
| auto& baseViewFormat = table[ComputeFormatIndex(f.baseFormat)].baseViewFormat; | |
| // Currently, Dawn only supports sRGB reinterpretation, so there should only be one | |
| // view format. | |
| DAWN_CHECK(baseViewFormat == wgpu::TextureFormat::Undefined); | |
| baseViewFormat = f.format; | |
| } | |
| } | |
| return table; | |
| } | |
| absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert( | |
| const UnsupportedReason& value, | |
| const absl::FormatConversionSpec& spec, | |
| absl::FormatSink* s) { | |
| MatchVariant( | |
| value, [](const std::monostate&) { DAWN_UNREACHABLE(); }, | |
| [s](const RequiresFeature& requiresFeature) { | |
| s->Append(absl::StrFormat("requires feature %s", requiresFeature.feature)); | |
| }, | |
| [s](const CompatibilityMode&) { s->Append("not supported in compatibility mode"); }); | |
| return {true}; | |
| } | |
| } // namespace dawn::native |