Generalize multi-aspect formats

Removes special casing depth-stencil or multi-planar formats.
Like depth-stencil, NV12 views can be created but not sampled.

BUG=dawn:551

Change-Id: I3cd43d079253f4ee45660d0efd2723e1650f88d3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/41342
Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Bryan Bernhart <bryan.bernhart@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Bryan Bernhart 2021-02-16 19:55:09 +00:00 committed by Commit Bot service account
parent 6dd34f7e34
commit 536c7aea7d
8 changed files with 115 additions and 108 deletions

View File

@ -1819,23 +1819,24 @@
{"value": 37, "name": "depth32 float"}, {"value": 37, "name": "depth32 float"},
{"value": 38, "name": "depth24 plus"}, {"value": 38, "name": "depth24 plus"},
{"value": 39, "name": "depth24 plus stencil8"}, {"value": 39, "name": "stencil8"},
{"value": 40, "name": "depth24 plus stencil8"},
{"value": 40, "name": "BC1 RGBA unorm"}, {"value": 41, "name": "BC1 RGBA unorm"},
{"value": 41, "name": "BC1 RGBA unorm srgb"}, {"value": 42, "name": "BC1 RGBA unorm srgb"},
{"value": 42, "name": "BC2 RGBA unorm"}, {"value": 43, "name": "BC2 RGBA unorm"},
{"value": 43, "name": "BC2 RGBA unorm srgb"}, {"value": 44, "name": "BC2 RGBA unorm srgb"},
{"value": 44, "name": "BC3 RGBA unorm"}, {"value": 45, "name": "BC3 RGBA unorm"},
{"value": 45, "name": "BC3 RGBA unorm srgb"}, {"value": 46, "name": "BC3 RGBA unorm srgb"},
{"value": 46, "name": "BC4 R unorm"}, {"value": 47, "name": "BC4 R unorm"},
{"value": 47, "name": "BC4 R snorm"}, {"value": 48, "name": "BC4 R snorm"},
{"value": 48, "name": "BC5 RG unorm"}, {"value": 49, "name": "BC5 RG unorm"},
{"value": 49, "name": "BC5 RG snorm"}, {"value": 50, "name": "BC5 RG snorm"},
{"value": 50, "name": "BC6H RGB ufloat"}, {"value": 51, "name": "BC6H RGB ufloat"},
{"value": 51, "name": "BC6H RGB float"}, {"value": 52, "name": "BC6H RGB float"},
{"value": 52, "name": "BC7 RGBA unorm"}, {"value": 53, "name": "BC7 RGBA unorm"},
{"value": 53, "name": "BC7 RGBA unorm srgb"}, {"value": 54, "name": "BC7 RGBA unorm srgb"},
{"value": 54, "name": "R8 BG8 Biplanar 420 unorm"} {"value": 55, "name": "R8 BG8 Biplanar 420 unorm"}
] ]
}, },
"texture usage": { "texture usage": {

View File

@ -15,6 +15,7 @@
#include "dawn_native/Format.h" #include "dawn_native/Format.h"
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
#include "dawn_native/EnumMaskIterator.h"
#include "dawn_native/Extensions.h" #include "dawn_native/Extensions.h"
#include "dawn_native/Texture.h" #include "dawn_native/Texture.h"
@ -22,22 +23,6 @@
namespace dawn_native { namespace dawn_native {
namespace {
static const AspectInfo kStencil8AspectInfo = {{1, 1, 1},
wgpu::TextureComponentType::Uint,
ComponentTypeBit::Uint};
// R8BG8Biplanar420Unorm must be specialized since it represents planar data and cannot be
// used without a per plane format. In particular, the component type is float since
// Dawn does not allow texture format reinterpretion (ex. using R8BG82plane420 with Uint or
// Unorm). Block size is always zero since the format is not renderable or copyable.
static const AspectInfo kR8BG8Biplanar420UnormAspectInfo = {
{0, 0, 0},
wgpu::TextureComponentType::Float,
ComponentTypeBit::Float};
}
// Format // Format
// TODO(dawn:527): Remove when unused. // TODO(dawn:527): Remove when unused.
@ -113,50 +98,21 @@ namespace dawn_native {
} }
const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const { const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const {
return GetAspectInfo(ConvertAspect(*this, aspect)); return GetAspectInfo(SelectFormatAspects(*this, aspect));
} }
const AspectInfo& Format::GetAspectInfo(Aspect aspect) const { const AspectInfo& Format::GetAspectInfo(Aspect aspect) const {
ASSERT(HasOneBit(aspect)); ASSERT(HasOneBit(aspect));
ASSERT(aspects & aspect); ASSERT(aspects & aspect);
const size_t aspectIndex = GetAspectIndex(aspect);
// The stencil aspect is the only aspect that's not the first aspect. Since it is always the ASSERT(aspectIndex < GetAspectCount(aspects));
// same aspect information, special case it to return a constant AspectInfo. return aspectInfo[aspectIndex];
if (aspect == Aspect::Stencil) {
return kStencil8AspectInfo;
// multi-planar formats are specified per plane aspect. Since it does not support
// non-planar access, it can always be the same aspect information, special cased to
// return a constant AspectInfo.
// TODO(dawn:551): Refactor and remove GetAspectFormat.
} else if (format == wgpu::TextureFormat::R8BG8Biplanar420Unorm) {
return kR8BG8Biplanar420UnormAspectInfo;
} else {
return firstAspect;
}
} }
size_t Format::GetIndex() const { size_t Format::GetIndex() const {
return ComputeFormatIndex(format); return ComputeFormatIndex(format);
} }
wgpu::TextureFormat Format::GetAspectFormat(wgpu::TextureAspect aspect) const {
switch (format) {
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
switch (aspect) {
case wgpu::TextureAspect::Plane0Only:
return wgpu::TextureFormat::R8Unorm;
case wgpu::TextureAspect::Plane1Only:
return wgpu::TextureFormat::RG8Unorm;
default:
return wgpu::TextureFormat::Undefined;
}
break;
// TODO(dawn:551): Consider using for depth-stencil formats.
default:
return format;
}
}
// Implementation details of the format table of the DeviceBase // 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 extension // For the enum for formats are packed but this might change when we have a broader extension
@ -185,9 +141,9 @@ namespace dawn_native {
// Vulkan describes bytesPerRow in units of texels. If there's any format for which this // Vulkan describes bytesPerRow in units of texels. If there's any format for which this
// ASSERT isn't true, then additional validation on bytesPerRow must be added. // ASSERT isn't true, then additional validation on bytesPerRow must be added.
// Multi-planar formats are not copyable and have no first aspect. const bool hasMultipleAspects = !HasOneBit(format.aspects);
ASSERT(format.IsMultiPlanar() || ASSERT(hasMultipleAspects ||
(kTextureBytesPerRowAlignment % format.firstAspect.block.byteSize) == 0); (kTextureBytesPerRowAlignment % format.aspectInfo[0].block.byteSize) == 0);
table[index] = format; table[index] = format;
formatsSet.set(index); formatsSet.set(index);
@ -203,29 +159,50 @@ namespace dawn_native {
internalFormat.isSupported = true; internalFormat.isSupported = true;
internalFormat.supportsStorageUsage = supportsStorageUsage; internalFormat.supportsStorageUsage = supportsStorageUsage;
internalFormat.aspects = Aspect::Color; internalFormat.aspects = Aspect::Color;
internalFormat.firstAspect.block.byteSize = byteSize; AspectInfo* firstAspect = internalFormat.aspectInfo.data();
internalFormat.firstAspect.block.width = 1; firstAspect->block.byteSize = byteSize;
internalFormat.firstAspect.block.height = 1; firstAspect->block.width = 1;
internalFormat.firstAspect.baseType = type; firstAspect->block.height = 1;
internalFormat.firstAspect.supportedComponentTypes = ToComponentTypeBit(type); firstAspect->baseType = type;
firstAspect->supportedComponentTypes = ToComponentTypeBit(type);
firstAspect->format = format;
AddFormat(internalFormat); AddFormat(internalFormat);
}; };
auto AddDepthStencilFormat = [&AddFormat](wgpu::TextureFormat format, Aspect aspects, auto AddDepthFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize) {
uint32_t byteSize) {
Format internalFormat; Format internalFormat;
internalFormat.format = format; internalFormat.format = format;
internalFormat.isRenderable = true; internalFormat.isRenderable = true;
internalFormat.isCompressed = false; internalFormat.isCompressed = false;
internalFormat.isSupported = true; internalFormat.isSupported = true;
internalFormat.supportsStorageUsage = false; internalFormat.supportsStorageUsage = false;
internalFormat.aspects = aspects; internalFormat.aspects = Aspect::Depth;
internalFormat.firstAspect.block.byteSize = byteSize; AspectInfo* firstAspect = internalFormat.aspectInfo.data();
internalFormat.firstAspect.block.width = 1; firstAspect->block.byteSize = byteSize;
internalFormat.firstAspect.block.height = 1; firstAspect->block.width = 1;
internalFormat.firstAspect.baseType = wgpu::TextureComponentType::Float; firstAspect->block.height = 1;
internalFormat.firstAspect.supportedComponentTypes = firstAspect->baseType = wgpu::TextureComponentType::Float;
firstAspect->supportedComponentTypes =
ComponentTypeBit::Float | ComponentTypeBit::DepthComparison; ComponentTypeBit::Float | ComponentTypeBit::DepthComparison;
firstAspect->format = format;
AddFormat(internalFormat);
};
auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format) {
Format internalFormat;
internalFormat.format = format;
internalFormat.isRenderable = true;
internalFormat.isCompressed = false;
internalFormat.isSupported = false;
internalFormat.supportsStorageUsage = false;
internalFormat.aspects = Aspect::Stencil;
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
firstAspect->block.byteSize = 1;
firstAspect->block.width = 1;
firstAspect->block.height = 1;
firstAspect->baseType = wgpu::TextureComponentType::Uint;
firstAspect->supportedComponentTypes = ComponentTypeBit::Uint;
firstAspect->format = format;
AddFormat(internalFormat); AddFormat(internalFormat);
}; };
@ -238,23 +215,34 @@ namespace dawn_native {
internalFormat.isSupported = isSupported; internalFormat.isSupported = isSupported;
internalFormat.supportsStorageUsage = false; internalFormat.supportsStorageUsage = false;
internalFormat.aspects = Aspect::Color; internalFormat.aspects = Aspect::Color;
internalFormat.firstAspect.block.byteSize = byteSize; AspectInfo* firstAspect = internalFormat.aspectInfo.data();
internalFormat.firstAspect.block.width = width; firstAspect->block.byteSize = byteSize;
internalFormat.firstAspect.block.height = height; firstAspect->block.width = width;
internalFormat.firstAspect.baseType = wgpu::TextureComponentType::Float; firstAspect->block.height = height;
internalFormat.firstAspect.supportedComponentTypes = ComponentTypeBit::Float; firstAspect->baseType = wgpu::TextureComponentType::Float;
firstAspect->supportedComponentTypes = ComponentTypeBit::Float;
firstAspect->format = format;
AddFormat(internalFormat); AddFormat(internalFormat);
}; };
auto AddMultiPlanarFormat = [&AddFormat](wgpu::TextureFormat format, Aspect aspects, auto AddMultiAspectFormat = [&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
bool isSupported) { wgpu::TextureFormat firstFormat,
wgpu::TextureFormat secondFormat,
bool isRenderable, bool isSupported) {
Format internalFormat; Format internalFormat;
internalFormat.format = format; internalFormat.format = format;
internalFormat.isRenderable = false; internalFormat.isRenderable = isRenderable;
internalFormat.isCompressed = false; internalFormat.isCompressed = false;
internalFormat.isSupported = isSupported; internalFormat.isSupported = isSupported;
internalFormat.supportsStorageUsage = false; internalFormat.supportsStorageUsage = false;
internalFormat.aspects = aspects; internalFormat.aspects = aspects;
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
internalFormat.aspectInfo[0] = table[firstFormatIndex].aspectInfo[0];
internalFormat.aspectInfo[1] = table[secondFormatIndex].aspectInfo[0];
AddFormat(internalFormat); AddFormat(internalFormat);
}; };
@ -308,12 +296,14 @@ namespace dawn_native {
AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, Type::Float); AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, Type::Float);
// Depth-stencil formats // Depth-stencil formats
AddDepthStencilFormat(wgpu::TextureFormat::Depth32Float, Aspect::Depth, 4); AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4);
AddDepthStencilFormat(wgpu::TextureFormat::Depth24Plus, Aspect::Depth, 4); AddDepthFormat(wgpu::TextureFormat::Depth24Plus, 4);
// TODO(dawn:666): Implement the stencil8 format
AddStencilFormat(wgpu::TextureFormat::Stencil8);
// TODO(cwallez@chromium.org): It isn't clear if this format should be copyable // TODO(cwallez@chromium.org): It isn't clear if this format should be copyable
// because its size isn't well defined, is it 4, 5 or 8? // because its size isn't well defined, is it 4, 5 or 8?
AddDepthStencilFormat(wgpu::TextureFormat::Depth24PlusStencil8, AddMultiAspectFormat(wgpu::TextureFormat::Depth24PlusStencil8,
Aspect::Depth | Aspect::Stencil, 4); Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8, true, true);
// BC compressed formats // BC compressed formats
bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC); bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
@ -334,7 +324,8 @@ namespace dawn_native {
// multi-planar formats // multi-planar formats
const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats); const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats);
AddMultiPlanarFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1, isMultiPlanarFormatSupported); AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, false, isMultiPlanarFormatSupported);
// clang-format on // clang-format on

View File

@ -68,11 +68,16 @@ namespace dawn_native {
TexelBlockInfo block; TexelBlockInfo block;
wgpu::TextureComponentType baseType; wgpu::TextureComponentType baseType;
ComponentTypeBit supportedComponentTypes; ComponentTypeBit supportedComponentTypes;
wgpu::TextureFormat format;
}; };
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the // The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
// exact number of known format. // exact number of known format.
static constexpr size_t kKnownFormatCount = 54; static constexpr size_t kKnownFormatCount = 55;
// The maximum number of planes per format Dawn knows about. Asserts in BuildFormatTable that
// the per plane index does not exceed the known maximum plane count
static constexpr uint32_t kMaxPlanesPerFormat = 2;
struct Format; struct Format;
using FormatTable = std::array<Format, kKnownFormatCount>; using FormatTable = std::array<Format, kKnownFormatCount>;
@ -103,14 +108,12 @@ namespace dawn_native {
// in [0, kKnownFormatCount) // in [0, kKnownFormatCount)
size_t GetIndex() const; size_t GetIndex() const;
// Used to lookup the compatible view format using an aspect which corresponds to the
// plane index. Returns Undefined if the wrong plane aspect is requested.
wgpu::TextureFormat GetAspectFormat(wgpu::TextureAspect aspect) const;
private: private:
// The most common aspect: the color aspect for color texture, the depth aspect for // Used to store the aspectInfo for one or more planes. For single plane "color" formats,
// depth[-stencil] textures. // only the first aspect info or aspectInfo[0] is valid. For depth-stencil, the first aspect
AspectInfo firstAspect; // info is depth and the second aspect info is stencil. For multi-planar formats,
// aspectInfo[i] is the ith plane.
std::array<AspectInfo, kMaxPlanesPerFormat> aspectInfo;
friend FormatTable BuildFormatTable(const DeviceBase* device); friend FormatTable BuildFormatTable(const DeviceBase* device);
}; };

View File

@ -29,7 +29,13 @@ namespace dawn_native {
// TODO(jiawei.shao@intel.com): implement texture view format compatibility rule // TODO(jiawei.shao@intel.com): implement texture view format compatibility rule
MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture, MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture,
const TextureViewDescriptor* descriptor) { const TextureViewDescriptor* descriptor) {
if (texture->GetFormat().GetAspectFormat(descriptor->aspect) != descriptor->format) { if (texture->GetFormat().format != descriptor->format) {
if (descriptor->aspect != wgpu::TextureAspect::All &&
texture->GetFormat().GetAspectInfo(descriptor->aspect).format ==
descriptor->format) {
return {};
}
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"The format of texture view is not compatible to the original texture"); "The format of texture view is not compatible to the original texture");
} }
@ -357,7 +363,8 @@ namespace dawn_native {
} }
if (desc.format == wgpu::TextureFormat::Undefined) { if (desc.format == wgpu::TextureFormat::Undefined) {
desc.format = texture->GetFormat().GetAspectFormat(desc.aspect); // TODO(dawn:682): Use GetAspectInfo(aspect).
desc.format = texture->GetFormat().format;
} }
if (desc.arrayLayerCount == 0) { if (desc.arrayLayerCount == 0) {
desc.arrayLayerCount = texture->GetArrayLayers() - desc.baseArrayLayer; desc.arrayLayerCount = texture->GetArrayLayers() - desc.baseArrayLayer;

View File

@ -203,6 +203,7 @@ namespace dawn_native { namespace d3d12 {
return DXGI_FORMAT_BC7_TYPELESS; return DXGI_FORMAT_BC7_TYPELESS;
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -328,6 +329,7 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
return DXGI_FORMAT_NV12; return DXGI_FORMAT_NV12;
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -1098,7 +1100,9 @@ namespace dawn_native { namespace d3d12 {
// Per plane view formats must have the plane slice number be the index of the plane in the // Per plane view formats must have the plane slice number be the index of the plane in the
// array of textures. // array of textures.
if (texture->GetFormat().IsMultiPlanar()) { if (texture->GetFormat().IsMultiPlanar()) {
planeSlice = GetAspectIndex(ConvertViewAspect(GetFormat(), descriptor->aspect)); const Aspect planeAspect = ConvertViewAspect(GetFormat(), descriptor->aspect);
planeSlice = GetAspectIndex(planeAspect);
mSrvDesc.Format = D3D12TextureFormat(GetFormat().GetAspectInfo(planeAspect).format);
} }
// Currently we always use D3D12_TEX2D_ARRAY_SRV because we cannot specify base array layer // Currently we always use D3D12_TEX2D_ARRAY_SRV because we cannot specify base array layer

View File

@ -339,6 +339,7 @@ namespace dawn_native { namespace vulkan {
case wgpu::TextureFormat::BC7RGBAUnormSrgb: case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return VK_FORMAT_BC7_SRGB_BLOCK; return VK_FORMAT_BC7_SRGB_BLOCK;
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -43,9 +43,6 @@ namespace {
wgpu::Texture videoTexture = CreateVideoTextureForTest( wgpu::Texture videoTexture = CreateVideoTextureForTest(
wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::None); wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::None);
// Create a default view with no plane selected.
ASSERT_DEVICE_ERROR(videoTexture.CreateView());
wgpu::TextureViewDescriptor viewDesc = {}; wgpu::TextureViewDescriptor viewDesc = {};
// Correct plane index but incompatible view format. // Correct plane index but incompatible view format.

View File

@ -113,6 +113,7 @@ namespace utils {
// Block size of a multi-planar format depends on aspect. // Block size of a multi-planar format depends on aspect.
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -180,6 +181,7 @@ namespace utils {
// Block size of a multi-planar format depends on aspect. // Block size of a multi-planar format depends on aspect.
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -247,6 +249,7 @@ namespace utils {
// Block size of a multi-planar format depends on aspect. // Block size of a multi-planar format depends on aspect.
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }