blob: 3b85b02af4a2d196b8bc1816b6cc5669e3d7f208 [file] [log] [blame]
// 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 "dawn/native/Format.h"
#include <bitset>
#include <optional>
#include <utility>
#include "dawn/common/MatchVariant.h"
#include "dawn/common/TypedInteger.h"
#include "dawn/native/Device.h"
#include "dawn/native/EnumMaskIterator.h"
#include "dawn/native/Features.h"
#include "dawn/native/Texture.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_ASSERT(HasOneBit(aspect));
DAWN_ASSERT(aspects & aspect);
const size_t aspectIndex = GetAspectIndex(aspect);
DAWN_ASSERT(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);
return static_cast<FormatIndex>(formatValue - 1);
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) {
// 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_ASSERT(index < table.size());
Format& format = table[index];
if (supported) {
format.caps = caps; // set the initial capabilities
format.unsupportedReason = Format::supported;
} else if (format.caps == Cap::None) {
auto requestedFeature = *feature;
format.unsupportedReason =
requestedFeature == Feature::CoreFeaturesAndLimits
? UnsupportedReason{CompatibilityMode{}}
: UnsupportedReason{
RequiresFeature{static_cast<wgpu::FeatureName>(requestedFeature)}};
}
}
};
// Add caps for the supported formats
auto AddCaps = [&](std::initializer_list<wgpu::TextureFormat> formats, Cap caps) {
DAWN_ASSERT(caps != Cap::None);
for (wgpu::TextureFormat fmt : formats) {
FormatIndex index = ComputeFormatIndex(fmt);
DAWN_ASSERT(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
InitialCapsAddedBy(Feature::YCbCrVulkanSamplers, {wgpu::TextureFormat::External}, Cap::None);
InitialCapsAddedBy(Feature::Unorm16TextureFormats,
{wgpu::TextureFormat::R16Unorm, wgpu::TextureFormat::RG16Unorm,
wgpu::TextureFormat::RGBA16Unorm},
Cap::Renderable | Cap::Multisample | Cap::Resolve);
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);
}
}
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_ASSERT(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_ASSERT(!formatsSet[index]);
// Vulkan describes bytesPerRow in units of texels. If there's any format for which this
// DAWN_ASSERT isn't true, then additional validation on bytesPerRow must be added.
const bool hasMultipleAspects = !HasOneBit(format.aspects);
DAWN_ASSERT(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(0),
RenderTargetComponentAlignment rtComponentAlign = RenderTargetComponentAlignment(0),
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(0)) {
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:
case SampleTypeBit::External:
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;
// 1 byte
DefineColorFormat(wgpu::TextureFormat::R8Unorm, ByteSize(1), kAnyFloat, ComponentCount(1),
RenderTargetPixelByteCost(1), RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::R8Snorm, ByteSize(1), kAnyFloat, ComponentCount(1),
RenderTargetPixelByteCost(1), RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::R8Uint, ByteSize(1), SampleTypeBit::Uint,
ComponentCount(1), RenderTargetPixelByteCost(1),
RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::R8Sint, ByteSize(1), SampleTypeBit::Sint,
ComponentCount(1), RenderTargetPixelByteCost(1),
RenderTargetComponentAlignment(1));
// 2 bytes
DefineColorFormat(wgpu::TextureFormat::R16Uint, ByteSize(2), SampleTypeBit::Uint,
ComponentCount(1), RenderTargetPixelByteCost(2),
RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::R16Sint, ByteSize(2), SampleTypeBit::Sint,
ComponentCount(1), RenderTargetPixelByteCost(2),
RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::R16Float, ByteSize(2), kAnyFloat, ComponentCount(1),
RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RG8Unorm, ByteSize(2), kAnyFloat, ComponentCount(2),
RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::RG8Snorm, ByteSize(2), kAnyFloat, ComponentCount(2),
RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RG8Uint, ByteSize(2), SampleTypeBit::Uint,
ComponentCount(2), RenderTargetPixelByteCost(2),
RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::RG8Sint, ByteSize(2), SampleTypeBit::Sint,
ComponentCount(2), RenderTargetPixelByteCost(2),
RenderTargetComponentAlignment(1));
// 4 bytes
DefineColorFormat(wgpu::TextureFormat::R32Uint, ByteSize(4), SampleTypeBit::Uint,
ComponentCount(1), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::R32Sint, ByteSize(4), SampleTypeBit::Sint,
ComponentCount(1), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::R32Float, ByteSize(4), sampleTypeFor32BitFloatFormats,
ComponentCount(1), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RG16Uint, ByteSize(4), SampleTypeBit::Uint,
ComponentCount(2), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RG16Sint, ByteSize(4), SampleTypeBit::Sint,
ComponentCount(2), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RG16Float, ByteSize(4), kAnyFloat, ComponentCount(2),
RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RGBA8Unorm, ByteSize(4), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, ByteSize(4), kAnyFloat,
ComponentCount(4), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(1), wgpu::TextureFormat::RGBA8Unorm);
DefineColorFormat(wgpu::TextureFormat::RGBA8Snorm, ByteSize(4), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RGBA8Uint, ByteSize(4), SampleTypeBit::Uint,
ComponentCount(4), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::RGBA8Sint, ByteSize(4), SampleTypeBit::Sint,
ComponentCount(4), RenderTargetPixelByteCost(4),
RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::BGRA8Unorm, ByteSize(4), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1));
DefineColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, ByteSize(4), kAnyFloat,
ComponentCount(4), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(1), wgpu::TextureFormat::BGRA8Unorm);
DefineColorFormat(wgpu::TextureFormat::RGB10A2Uint, ByteSize(4), SampleTypeBit::Uint,
ComponentCount(4), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RGB10A2Unorm, ByteSize(4), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RG11B10Ufloat, ByteSize(4), kAnyFloat, ComponentCount(3),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, ByteSize(4), kAnyFloat, ComponentCount(3));
DefineColorFormat(wgpu::TextureFormat::External, ByteSize(1), SampleTypeBit::External,
ComponentCount(0));
// 8 bytes
DefineColorFormat(wgpu::TextureFormat::RG32Uint, ByteSize(8), SampleTypeBit::Uint,
ComponentCount(2), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RG32Sint, ByteSize(8), SampleTypeBit::Sint,
ComponentCount(2), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RG32Float, ByteSize(8), sampleTypeFor32BitFloatFormats,
ComponentCount(2), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RGBA16Uint, ByteSize(8), SampleTypeBit::Uint,
ComponentCount(4), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RGBA16Sint, ByteSize(8), SampleTypeBit::Sint,
ComponentCount(4), RenderTargetPixelByteCost(8),
RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RGBA16Float, ByteSize(8), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
// 16 bytes
DefineColorFormat(wgpu::TextureFormat::RGBA32Uint, ByteSize(16), SampleTypeBit::Uint,
ComponentCount(4), RenderTargetPixelByteCost(16),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RGBA32Sint, ByteSize(16), SampleTypeBit::Sint,
ComponentCount(4), RenderTargetPixelByteCost(16),
RenderTargetComponentAlignment(4));
DefineColorFormat(wgpu::TextureFormat::RGBA32Float, ByteSize(16),
sampleTypeFor32BitFloatFormats, ComponentCount(4),
RenderTargetPixelByteCost(16), RenderTargetComponentAlignment(4));
// Norm16
DefineColorFormat(wgpu::TextureFormat::R16Unorm, ByteSize(2), kAnyFloat, ComponentCount(1),
RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RG16Unorm, ByteSize(4), kAnyFloat, ComponentCount(2),
RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RGBA16Unorm, ByteSize(8), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::R16Snorm, ByteSize(2), kAnyFloat, ComponentCount(1),
RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RG16Snorm, ByteSize(4), kAnyFloat, ComponentCount(2),
RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
DefineColorFormat(wgpu::TextureFormat::RGBA16Snorm, ByteSize(8), kAnyFloat, ComponentCount(4),
RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
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_ASSERT(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_ASSERT(table[firstFormatIndex].aspectInfo[0].format !=
wgpu::TextureFormat::Undefined);
DAWN_ASSERT(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);
};
// 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(2), 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(2), 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(8), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4));
AddBCCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, ByteSize(8), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::BC1RGBAUnorm);
AddBCCompressedFormat(wgpu::TextureFormat::BC4RSnorm, ByteSize(8), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(1));
AddBCCompressedFormat(wgpu::TextureFormat::BC4RUnorm, ByteSize(8), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(1));
AddBCCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4));
AddBCCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::BC2RGBAUnorm);
AddBCCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4));
AddBCCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::BC3RGBAUnorm);
AddBCCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(2));
AddBCCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(2));
AddBCCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(3));
AddBCCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(3));
AddBCCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4));
AddBCCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, ByteSize(16), Width(4), Height(4), bcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::BC7RGBAUnorm);
// ETC2/EAC compressed formats
UnsupportedReason etc2FormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionETC2) ? Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionETC2};
AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, ByteSize(8), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(3));
AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, ByteSize(8), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(3), wgpu::TextureFormat::ETC2RGB8Unorm);
AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, ByteSize(8), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(4));
AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, ByteSize(8), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ETC2RGB8A1Unorm);
AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, ByteSize(16), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(4));
AddETCCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, ByteSize(16), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ETC2RGBA8Unorm);
AddETCCompressedFormat(wgpu::TextureFormat::EACR11Unorm, ByteSize(8), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(1));
AddETCCompressedFormat(wgpu::TextureFormat::EACR11Snorm, ByteSize(8), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(1));
AddETCCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, ByteSize(16), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(2));
AddETCCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, ByteSize(16), Width(4), Height(4), etc2FormatUnsupportedReason, ComponentCount(2));
// ASTC compressed formats
UnsupportedReason astcFormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionASTC) ? Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionASTC};
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, ByteSize(16), Width(4), Height(4), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, ByteSize(16), Width(4), Height(4), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC4x4Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, ByteSize(16), Width(5), Height(4), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, ByteSize(16), Width(5), Height(4), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC5x4Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, ByteSize(16), Width(5), Height(5), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, ByteSize(16), Width(5), Height(5), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC5x5Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, ByteSize(16), Width(6), Height(5), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, ByteSize(16), Width(6), Height(5), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC6x5Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, ByteSize(16), Width(6), Height(6), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, ByteSize(16), Width(6), Height(6), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC6x6Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, ByteSize(16), Width(8), Height(5), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, ByteSize(16), Width(8), Height(5), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC8x5Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, ByteSize(16), Width(8), Height(6), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, ByteSize(16), Width(8), Height(6), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC8x6Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, ByteSize(16), Width(8), Height(8), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, ByteSize(16), Width(8), Height(8), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC8x8Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, ByteSize(16), Width(10), Height(5), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, ByteSize(16), Width(10), Height(5), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC10x5Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, ByteSize(16), Width(10), Height(6), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, ByteSize(16), Width(10), Height(6), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC10x6Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, ByteSize(16), Width(10), Height(8), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, ByteSize(16), Width(10), Height(8), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC10x8Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, ByteSize(16), Width(10), Height(10), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, ByteSize(16), Width(10), Height(10), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC10x10Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, ByteSize(16), Width(12), Height(10), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, ByteSize(16), Width(12), Height(10), astcFormatUnsupportedReason, ComponentCount(4), wgpu::TextureFormat::ASTC12x10Unorm);
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, ByteSize(16), Width(12), Height(12), astcFormatUnsupportedReason, ComponentCount(4));
AddASTCCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, ByteSize(16), Width(12), Height(12), astcFormatUnsupportedReason, ComponentCount(4), 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(3), 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(3), 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(3), 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(3), 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(3), 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(3), 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(4), 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_ASSERT(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_ASSERT(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