Support T2T copies between formats that have only difference on srgb-ness

In previous T2T copy, Dawn requires textures have the same formats. But
Vulkan/Metal/D3D12 have ability to copy between "compatible" formats textures.

Metal has the most restrict rules without setting interpreter flags when creating
textures. It defines "compatible" texture formats to the formats that only have
difference on srgb-ness.

This CL follow Metal's rule and release the validations for T2T copies. It supports
T2T copy between "compatible" texture format textures.

Bug: dawn:1204
Change-Id: I50bf04ea15e8026530b3a5bdb5725f56aa192d85
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/74301
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
This commit is contained in:
Yan 2022-01-06 09:01:58 +00:00 committed by Dawn LUCI CQ
parent fa2fde1432
commit cf0e4fceb3
9 changed files with 482 additions and 120 deletions

View File

@ -429,11 +429,13 @@ namespace dawn_native {
MaybeError ValidateTextureToTextureCopyRestrictions(const ImageCopyTexture& src, MaybeError ValidateTextureToTextureCopyRestrictions(const ImageCopyTexture& src,
const ImageCopyTexture& dst, const ImageCopyTexture& dst,
const Extent3D& copySize) { const Extent3D& copySize) {
// Metal requires texture-to-texture copies be the same format // Metal requires texture-to-texture copies happens between texture formats that equal to
DAWN_INVALID_IF(src.texture->GetFormat().format != dst.texture->GetFormat().format, // each other or only have diff on srgb-ness.
"Source %s format (%s) and destination %s format (%s) do not match.", DAWN_INVALID_IF(
src.texture, src.texture->GetFormat().format, dst.texture, !src.texture->GetFormat().CopyCompatibleWith(dst.texture->GetFormat()),
dst.texture->GetFormat().format); "Source %s format (%s) and destination %s format (%s) are not copy compatible.",
src.texture, src.texture->GetFormat().format, dst.texture,
dst.texture->GetFormat().format);
return ValidateTextureToTextureCopyCommonRestrictions(src, dst, copySize); return ValidateTextureToTextureCopyCommonRestrictions(src, dst, copySize);
} }

View File

@ -104,6 +104,10 @@ namespace dawn_native {
return (aspects & (Aspect::Plane0 | Aspect::Plane1)) != 0; return (aspects & (Aspect::Plane0 | Aspect::Plane1)) != 0;
} }
bool Format::CopyCompatibleWith(const Format& format) const {
return baseFormat == format.baseFormat;
}
const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const { const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const {
return GetAspectInfo(SelectFormatAspects(*this, aspect)); return GetAspectInfo(SelectFormatAspects(*this, aspect));
} }
@ -157,47 +161,57 @@ namespace dawn_native {
formatsSet.set(index); formatsSet.set(index);
}; };
auto AddColorFormat = [&AddFormat](wgpu::TextureFormat format, bool renderable, auto AddColorFormat =
bool supportsStorageUsage, uint32_t byteSize, [&AddFormat](wgpu::TextureFormat format, bool renderable, bool supportsStorageUsage,
SampleTypeBit sampleTypes, uint8_t componentCount) { uint32_t byteSize, SampleTypeBit sampleTypes, uint8_t componentCount,
Format internalFormat; wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
internalFormat.format = format; Format internalFormat;
internalFormat.isRenderable = renderable; internalFormat.format = format;
internalFormat.isCompressed = false; internalFormat.isRenderable = renderable;
internalFormat.isSupported = true; internalFormat.isCompressed = false;
internalFormat.supportsStorageUsage = supportsStorageUsage; internalFormat.isSupported = true;
internalFormat.aspects = Aspect::Color; internalFormat.supportsStorageUsage = supportsStorageUsage;
internalFormat.componentCount = componentCount; internalFormat.aspects = Aspect::Color;
AspectInfo* firstAspect = internalFormat.aspectInfo.data(); internalFormat.componentCount = componentCount;
firstAspect->block.byteSize = byteSize;
firstAspect->block.width = 1;
firstAspect->block.height = 1;
if (HasOneBit(sampleTypes)) {
switch (sampleTypes) {
case SampleTypeBit::Float:
case SampleTypeBit::UnfilterableFloat:
firstAspect->baseType = wgpu::TextureComponentType::Float;
break;
case SampleTypeBit::Sint:
firstAspect->baseType = wgpu::TextureComponentType::Sint;
break;
case SampleTypeBit::Uint:
firstAspect->baseType = wgpu::TextureComponentType::Uint;
break;
default:
UNREACHABLE();
}
} else {
ASSERT((sampleTypes & SampleTypeBit::Float) != 0);
firstAspect->baseType = wgpu::TextureComponentType::Float;
}
firstAspect->supportedSampleTypes = sampleTypes;
firstAspect->format = format;
AddFormat(internalFormat);
};
auto AddDepthFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize, // Default baseFormat of each color formats should be themselves.
bool isSupported) { if (baseFormat == wgpu::TextureFormat::Undefined) {
internalFormat.baseFormat = format;
} else {
internalFormat.baseFormat = baseFormat;
}
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
firstAspect->block.byteSize = byteSize;
firstAspect->block.width = 1;
firstAspect->block.height = 1;
if (HasOneBit(sampleTypes)) {
switch (sampleTypes) {
case SampleTypeBit::Float:
case SampleTypeBit::UnfilterableFloat:
firstAspect->baseType = wgpu::TextureComponentType::Float;
break;
case SampleTypeBit::Sint:
firstAspect->baseType = wgpu::TextureComponentType::Sint;
break;
case SampleTypeBit::Uint:
firstAspect->baseType = wgpu::TextureComponentType::Uint;
break;
default:
UNREACHABLE();
}
} else {
ASSERT((sampleTypes & SampleTypeBit::Float) != 0);
firstAspect->baseType = wgpu::TextureComponentType::Float;
}
firstAspect->supportedSampleTypes = sampleTypes;
firstAspect->format = format;
AddFormat(internalFormat);
};
auto AddDepthFormat = [&AddFormat](
wgpu::TextureFormat format, uint32_t byteSize, bool isSupported,
wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
Format internalFormat; Format internalFormat;
internalFormat.format = format; internalFormat.format = format;
internalFormat.isRenderable = true; internalFormat.isRenderable = true;
@ -206,6 +220,14 @@ namespace dawn_native {
internalFormat.supportsStorageUsage = false; internalFormat.supportsStorageUsage = false;
internalFormat.aspects = Aspect::Depth; internalFormat.aspects = Aspect::Depth;
internalFormat.componentCount = 1; internalFormat.componentCount = 1;
// Default baseFormat of each depth formats should be themselves.
if (baseFormat == wgpu::TextureFormat::Undefined) {
internalFormat.baseFormat = format;
} else {
internalFormat.baseFormat = baseFormat;
}
AspectInfo* firstAspect = internalFormat.aspectInfo.data(); AspectInfo* firstAspect = internalFormat.aspectInfo.data();
firstAspect->block.byteSize = byteSize; firstAspect->block.byteSize = byteSize;
firstAspect->block.width = 1; firstAspect->block.width = 1;
@ -216,7 +238,9 @@ namespace dawn_native {
AddFormat(internalFormat); AddFormat(internalFormat);
}; };
auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format, bool isSupported) { auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format, bool isSupported,
wgpu::TextureFormat baseFormat =
wgpu::TextureFormat::Undefined) {
Format internalFormat; Format internalFormat;
internalFormat.format = format; internalFormat.format = format;
internalFormat.isRenderable = true; internalFormat.isRenderable = true;
@ -225,6 +249,15 @@ namespace dawn_native {
internalFormat.supportsStorageUsage = false; internalFormat.supportsStorageUsage = false;
internalFormat.aspects = Aspect::Stencil; internalFormat.aspects = Aspect::Stencil;
internalFormat.componentCount = 1; internalFormat.componentCount = 1;
internalFormat.baseFormat = baseFormat;
// Default baseFormat of each stencil formats should be themselves.
if (baseFormat == wgpu::TextureFormat::Undefined) {
internalFormat.baseFormat = format;
} else {
internalFormat.baseFormat = baseFormat;
}
AspectInfo* firstAspect = internalFormat.aspectInfo.data(); AspectInfo* firstAspect = internalFormat.aspectInfo.data();
firstAspect->block.byteSize = 1; firstAspect->block.byteSize = 1;
firstAspect->block.width = 1; firstAspect->block.width = 1;
@ -235,31 +268,41 @@ namespace dawn_native {
AddFormat(internalFormat); AddFormat(internalFormat);
}; };
auto AddCompressedFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize, auto AddCompressedFormat =
uint32_t width, uint32_t height, bool isSupported, [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize, uint32_t width,
uint8_t componentCount) { uint32_t height, bool isSupported, uint8_t componentCount,
Format internalFormat; wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
internalFormat.format = format; Format internalFormat;
internalFormat.isRenderable = false; internalFormat.format = format;
internalFormat.isCompressed = true; internalFormat.isRenderable = false;
internalFormat.isSupported = isSupported; internalFormat.isCompressed = true;
internalFormat.supportsStorageUsage = false; internalFormat.isSupported = isSupported;
internalFormat.aspects = Aspect::Color; internalFormat.supportsStorageUsage = false;
internalFormat.componentCount = componentCount; internalFormat.aspects = Aspect::Color;
AspectInfo* firstAspect = internalFormat.aspectInfo.data(); internalFormat.componentCount = componentCount;
firstAspect->block.byteSize = byteSize;
firstAspect->block.width = width; // Default baseFormat of each compressed formats should be themselves.
firstAspect->block.height = height; if (baseFormat == wgpu::TextureFormat::Undefined) {
firstAspect->baseType = wgpu::TextureComponentType::Float; internalFormat.baseFormat = format;
firstAspect->supportedSampleTypes = kAnyFloat; } else {
firstAspect->format = format; internalFormat.baseFormat = baseFormat;
AddFormat(internalFormat); }
};
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
firstAspect->block.byteSize = byteSize;
firstAspect->block.width = width;
firstAspect->block.height = height;
firstAspect->baseType = wgpu::TextureComponentType::Float;
firstAspect->supportedSampleTypes = kAnyFloat;
firstAspect->format = format;
AddFormat(internalFormat);
};
auto AddMultiAspectFormat = auto AddMultiAspectFormat =
[&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects, [&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat, wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat,
bool isRenderable, bool isSupported, uint8_t componentCount) { bool isRenderable, bool isSupported, uint8_t componentCount,
wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
Format internalFormat; Format internalFormat;
internalFormat.format = format; internalFormat.format = format;
internalFormat.isRenderable = isRenderable; internalFormat.isRenderable = isRenderable;
@ -268,6 +311,14 @@ namespace dawn_native {
internalFormat.supportsStorageUsage = false; internalFormat.supportsStorageUsage = false;
internalFormat.aspects = aspects; internalFormat.aspects = aspects;
internalFormat.componentCount = componentCount; internalFormat.componentCount = componentCount;
// Default baseFormat of each multi aspect formats should be themselves.
if (baseFormat == wgpu::TextureFormat::Undefined) {
internalFormat.baseFormat = format;
} else {
internalFormat.baseFormat = baseFormat;
}
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat); const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat); const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
@ -301,12 +352,12 @@ namespace dawn_native {
AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, SampleTypeBit::Sint, 2); AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, SampleTypeBit::Sint, 2);
AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, kAnyFloat, 2); AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, kAnyFloat, 2);
AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, kAnyFloat, 4); AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, kAnyFloat, 4);
AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, kAnyFloat, 4); AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, kAnyFloat, 4, wgpu::TextureFormat::RGBA8Unorm);
AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, kAnyFloat, 4); AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, kAnyFloat, 4);
AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, SampleTypeBit::Uint, 4); AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, SampleTypeBit::Uint, 4);
AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, SampleTypeBit::Sint, 4); AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, SampleTypeBit::Sint, 4);
AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, kAnyFloat, 4); AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, kAnyFloat, 4);
AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, kAnyFloat, 4); AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, kAnyFloat, 4, wgpu::TextureFormat::BGRA8Unorm);
AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, kAnyFloat, 4); AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, kAnyFloat, 4);
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, 4, kAnyFloat, 3); AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, 4, kAnyFloat, 3);
@ -346,28 +397,28 @@ namespace dawn_native {
// BC compressed formats // BC compressed formats
bool isBCFormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionBC); bool isBCFormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionBC);
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC1RGBAUnorm);
AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported, 1); AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported, 1);
AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported, 1); AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported, 1);
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC2RGBAUnorm);
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC3RGBAUnorm);
AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported, 2); AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported, 2);
AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported, 2); AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported, 2);
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported, 3); AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported, 3);
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported, 3); AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported, 3);
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC7RGBAUnorm);
// ETC2/EAC compressed formats // ETC2/EAC compressed formats
bool isETC2FormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionETC2); bool isETC2FormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionETC2);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, 8, 4, 4, isETC2FormatSupported, 3); AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, 8, 4, 4, isETC2FormatSupported, 3);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, 8, 4, 4, isETC2FormatSupported, 3); AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, 8, 4, 4, isETC2FormatSupported, 3, wgpu::TextureFormat::ETC2RGB8Unorm);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, 8, 4, 4, isETC2FormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, 8, 4, 4, isETC2FormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, 8, 4, 4, isETC2FormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, 8, 4, 4, isETC2FormatSupported, 4, wgpu::TextureFormat::ETC2RGB8A1Unorm);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, 16, 4, 4, isETC2FormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, 16, 4, 4, isETC2FormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, 16, 4, 4, isETC2FormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, 16, 4, 4, isETC2FormatSupported, 4, wgpu::TextureFormat::ETC2RGBA8Unorm);
AddCompressedFormat(wgpu::TextureFormat::EACR11Unorm, 8, 4, 4, isETC2FormatSupported, 1); AddCompressedFormat(wgpu::TextureFormat::EACR11Unorm, 8, 4, 4, isETC2FormatSupported, 1);
AddCompressedFormat(wgpu::TextureFormat::EACR11Snorm, 8, 4, 4, isETC2FormatSupported, 1); AddCompressedFormat(wgpu::TextureFormat::EACR11Snorm, 8, 4, 4, isETC2FormatSupported, 1);
AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, isETC2FormatSupported, 2); AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, isETC2FormatSupported, 2);
@ -376,33 +427,33 @@ namespace dawn_native {
// ASTC compressed formats // ASTC compressed formats
bool isASTCFormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionASTC); bool isASTCFormatSupported = device->IsFeatureEnabled(Feature::TextureCompressionASTC);
AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC4x4Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, 16, 5, 4, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, 16, 5, 4, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC5x4Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, 16, 5, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, 16, 5, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, 16, 5, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, 16, 5, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC5x5Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, 16, 6, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, 16, 6, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, 16, 6, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, 16, 6, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC6x5Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, 16, 6, 6, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, 16, 6, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, 16, 6, 6, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, 16, 6, 6, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC6x6Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, 16, 8, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, 16, 8, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, 16, 8, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, 16, 8, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC8x5Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, 16, 8, 6, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, 16, 8, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, 16, 8, 6, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, 16, 8, 6, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC8x6Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, 16, 8, 8, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, 16, 8, 8, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, 16, 8, 8, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, 16, 8, 8, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC8x8Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, 16, 10, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, 16, 10, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, 16, 10, 5, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, 16, 10, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x5Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, 16, 10, 6, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, 16, 10, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, 16, 10, 6, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, 16, 10, 6, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x6Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, 16, 10, 8, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, 16, 10, 8, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, 16, 10, 8, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, 16, 10, 8, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x8Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, 16, 10, 10, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, 16, 10, 10, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, 16, 10, 10, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, 16, 10, 10, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x10Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, 16, 12, 10, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, 16, 12, 10, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, 16, 12, 10, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, 16, 12, 10, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC12x10Unorm);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, 16, 12, 12, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, 16, 12, 12, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, isASTCFormatSupported, 4); AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC12x12Unorm);
// multi-planar formats // multi-planar formats
const bool isMultiPlanarFormatSupported = device->IsFeatureEnabled(Feature::MultiPlanarFormats); const bool isMultiPlanarFormatSupported = device->IsFeatureEnabled(Feature::MultiPlanarFormats);

View File

@ -85,6 +85,7 @@ namespace dawn_native {
// A wgpu::TextureFormat along with all the information about it necessary for validation. // A wgpu::TextureFormat along with all the information about it necessary for validation.
struct Format { struct Format {
wgpu::TextureFormat format; wgpu::TextureFormat format;
bool isRenderable; bool isRenderable;
bool isCompressed; bool isCompressed;
// A format can be known but not supported because it is part of a disabled extension. // A format can be known but not supported because it is part of a disabled extension.
@ -110,6 +111,14 @@ namespace dawn_native {
// in [0, kKnownFormatCount) // in [0, kKnownFormatCount)
size_t GetIndex() const; size_t GetIndex() const;
// baseFormat represents the memory layout of the format.
// If two formats has the same baseFormat, they could copy to each other.
wgpu::TextureFormat baseFormat;
// CopyCompatibleWith() returns true if the input format has the same baseFormat
// with current format.
bool CopyCompatibleWith(const Format& format) const;
private: private:
// Used to store the aspectInfo for one or more planes. For single plane "color" formats, // Used to store the aspectInfo for one or more planes. For single plane "color" formats,
// only the first aspect info or aspectInfo[0] is valid. For depth-stencil, the first aspect // only the first aspect info or aspectInfo[0] is valid. For depth-stencil, the first aspect

View File

@ -64,7 +64,7 @@ namespace dawn_native { namespace d3d12 {
const Extent3D& copySize) { const Extent3D& copySize) {
// Checked by validation // Checked by validation
ASSERT(src.texture->GetSampleCount() == dst.texture->GetSampleCount()); ASSERT(src.texture->GetSampleCount() == dst.texture->GetSampleCount());
ASSERT(src.texture->GetFormat().format == dst.texture->GetFormat().format); ASSERT(src.texture->GetFormat().CopyCompatibleWith(dst.texture->GetFormat()));
ASSERT(src.aspect == dst.aspect); ASSERT(src.aspect == dst.aspect);
const Extent3D& srcSize = src.texture->GetSize(); const Extent3D& srcSize = src.texture->GetSize();
@ -168,7 +168,8 @@ namespace dawn_native { namespace d3d12 {
Toggle:: Toggle::
UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel)) { UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel)) {
bool copyToLesserLevel = srcCopy.mipLevel > dstCopy.mipLevel; bool copyToLesserLevel = srcCopy.mipLevel > dstCopy.mipLevel;
ASSERT(srcCopy.texture->GetFormat().format == dstCopy.texture->GetFormat().format); ASSERT(
srcCopy.texture->GetFormat().CopyCompatibleWith(dstCopy.texture->GetFormat()));
// GetAspectInfo(aspect) requires HasOneBit(aspect) == true, plus the texel block // GetAspectInfo(aspect) requires HasOneBit(aspect) == true, plus the texel block
// sizes of depth stencil formats are always no less than 4 bytes. // sizes of depth stencil formats are always no less than 4 bytes.

View File

@ -897,6 +897,10 @@ namespace dawn_native { namespace metal {
*sourceZPtr = copy->source.origin.z + z; *sourceZPtr = copy->source.origin.z + z;
*destinationZPtr = copy->destination.origin.z + z; *destinationZPtr = copy->destination.origin.z + z;
// Hold the ref until out of scope
NSPRef<id<MTLTexture>> dstTextureView =
dstTexture->CreateFormatView(srcTexture->GetFormat().format);
[commandContext->EnsureBlit() [commandContext->EnsureBlit()
copyFromTexture:srcTexture->GetMTLTexture() copyFromTexture:srcTexture->GetMTLTexture()
sourceSlice:sourceLayer sourceSlice:sourceLayer
@ -904,7 +908,7 @@ namespace dawn_native { namespace metal {
sourceOrigin:MTLOriginMake(copy->source.origin.x, sourceOrigin:MTLOriginMake(copy->source.origin.x,
copy->source.origin.y, sourceOriginZ) copy->source.origin.y, sourceOriginZ)
sourceSize:sizeOneSlice sourceSize:sizeOneSlice
toTexture:dstTexture->GetMTLTexture() toTexture:dstTextureView.Get()
destinationSlice:destinationLayer destinationSlice:destinationLayer
destinationLevel:copy->destination.mipLevel destinationLevel:copy->destination.mipLevel
destinationOrigin:MTLOriginMake(copy->destination.origin.x, destinationOrigin:MTLOriginMake(copy->destination.origin.x,

View File

@ -48,6 +48,7 @@ namespace dawn_native { namespace metal {
NSPRef<id<MTLTexture>> wrapped); NSPRef<id<MTLTexture>> wrapped);
id<MTLTexture> GetMTLTexture(); id<MTLTexture> GetMTLTexture();
NSPRef<id<MTLTexture>> CreateFormatView(wgpu::TextureFormat format);
void EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext, void EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
const SubresourceRange& range); const SubresourceRange& range);

View File

@ -113,6 +113,49 @@ namespace dawn_native { namespace metal {
return false; return false;
} }
// Metal only allows format reinterpretation to happen on swizzle pattern or conversion
// between linear space and sRGB without setting MTLTextureUsagePixelFormatView flag. For
// example, creating bgra8Unorm texture view on rgba8Unorm texture or creating
// rgba8Unorm_srgb texture view on rgab8Unorm texture.
bool AllowFormatReinterpretationWithoutFlag(MTLPixelFormat origin,
MTLPixelFormat reinterpretation) {
switch (origin) {
case MTLPixelFormatRGBA8Unorm:
return reinterpretation == MTLPixelFormatBGRA8Unorm ||
reinterpretation == MTLPixelFormatRGBA8Unorm_sRGB;
case MTLPixelFormatBGRA8Unorm:
return reinterpretation == MTLPixelFormatRGBA8Unorm ||
reinterpretation == MTLPixelFormatBGRA8Unorm_sRGB;
case MTLPixelFormatRGBA8Unorm_sRGB:
return reinterpretation == MTLPixelFormatBGRA8Unorm_sRGB ||
reinterpretation == MTLPixelFormatRGBA8Unorm;
case MTLPixelFormatBGRA8Unorm_sRGB:
return reinterpretation == MTLPixelFormatRGBA8Unorm_sRGB ||
reinterpretation == MTLPixelFormatBGRA8Unorm;
#if defined(DAWN_PLATFORM_MACOS)
case MTLPixelFormatBC1_RGBA:
return reinterpretation == MTLPixelFormatBC1_RGBA_sRGB;
case MTLPixelFormatBC1_RGBA_sRGB:
return reinterpretation == MTLPixelFormatBC1_RGBA;
case MTLPixelFormatBC2_RGBA:
return reinterpretation == MTLPixelFormatBC2_RGBA_sRGB;
case MTLPixelFormatBC2_RGBA_sRGB:
return reinterpretation == MTLPixelFormatBC2_RGBA;
case MTLPixelFormatBC3_RGBA:
return reinterpretation == MTLPixelFormatBC3_RGBA_sRGB;
case MTLPixelFormatBC3_RGBA_sRGB:
return reinterpretation == MTLPixelFormatBC3_RGBA;
case MTLPixelFormatBC7_RGBAUnorm:
return reinterpretation == MTLPixelFormatBC7_RGBAUnorm_sRGB;
case MTLPixelFormatBC7_RGBAUnorm_sRGB:
return reinterpretation == MTLPixelFormatBC7_RGBAUnorm;
#endif
default:
return false;
}
}
ResultOrError<wgpu::TextureFormat> GetFormatEquivalentToIOSurfaceFormat(uint32_t format) { ResultOrError<wgpu::TextureFormat> GetFormatEquivalentToIOSurfaceFormat(uint32_t format) {
switch (format) { switch (format) {
case kCVPixelFormatType_32RGBA: case kCVPixelFormatType_32RGBA:
@ -382,7 +425,10 @@ namespace dawn_native { namespace metal {
mtlDesc.width = GetWidth(); mtlDesc.width = GetWidth();
mtlDesc.height = GetHeight(); mtlDesc.height = GetHeight();
mtlDesc.sampleCount = GetSampleCount(); mtlDesc.sampleCount = GetSampleCount();
// TODO: add MTLTextureUsagePixelFormatView when needed when we support format // Metal only allows format reinterpretation to happen on swizzle pattern or conversion
// between linear space and sRGB. For example, creating bgra8Unorm texture view on
// rgba8Unorm texture or creating rgba8Unorm_srgb texture view on rgab8Unorm texture.
// TODO: add MTLTextureUsagePixelFormatView when needed when we support other format
// reinterpretation. // reinterpretation.
mtlDesc.usage = MetalTextureUsage(GetFormat(), GetInternalUsage(), GetSampleCount()); mtlDesc.usage = MetalTextureUsage(GetFormat(), GetInternalUsage(), GetSampleCount());
mtlDesc.pixelFormat = MetalPixelFormat(GetFormat().format); mtlDesc.pixelFormat = MetalPixelFormat(GetFormat().format);
@ -509,6 +555,17 @@ namespace dawn_native { namespace metal {
return mMtlTexture.Get(); return mMtlTexture.Get();
} }
NSPRef<id<MTLTexture>> Texture::CreateFormatView(wgpu::TextureFormat format) {
if (GetFormat().format == format) {
return mMtlTexture;
}
ASSERT(AllowFormatReinterpretationWithoutFlag(MetalPixelFormat(GetFormat().format),
MetalPixelFormat(format)));
return AcquireNSPRef(
[mMtlTexture.Get() newTextureViewWithPixelFormat:MetalPixelFormat(format)]);
}
MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext, MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext,
const SubresourceRange& range, const SubresourceRange& range,
TextureBase::ClearValue clearValue) { TextureBase::ClearValue clearValue) {

View File

@ -327,35 +327,25 @@ namespace {
// CopyTextureToTextureInternal. // CopyTextureToTextureInternal.
using UsageCopySrc = bool; using UsageCopySrc = bool;
DAWN_TEST_PARAM_STRUCT(CopyTestsParams, UsageCopySrc); DAWN_TEST_PARAM_STRUCT(CopyTestsParams, UsageCopySrc);
using SrcColorFormat = wgpu::TextureFormat;
DAWN_TEST_PARAM_STRUCT(SrcColorFormatParams, SrcColorFormat);
} // namespace } // namespace
class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParams> { template <typename Parent>
class CopyTests_T2TBase : public CopyTests, public Parent {
protected: protected:
std::vector<wgpu::FeatureName> GetRequiredFeatures() override { std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
return {wgpu::FeatureName::DawnInternalUsages}; return {wgpu::FeatureName::DawnInternalUsages};
} }
void DoTest(const TextureSpec& srcSpec,
const TextureSpec& dstSpec,
const wgpu::Extent3D& copySize,
bool copyWithinSameTexture = false,
wgpu::TextureDimension dimension = wgpu::TextureDimension::e2D) {
DoTest(srcSpec, dstSpec, copySize, dimension, dimension, copyWithinSameTexture);
}
void DoTest(const TextureSpec& srcSpec, void DoTest(const TextureSpec& srcSpec,
const TextureSpec& dstSpec, const TextureSpec& dstSpec,
const wgpu::Extent3D& copySize, const wgpu::Extent3D& copySize,
wgpu::TextureDimension srcDimension, wgpu::TextureDimension srcDimension,
wgpu::TextureDimension dstDimension, wgpu::TextureDimension dstDimension,
bool copyWithinSameTexture = false) { bool copyWithinSameTexture = false,
const bool usageCopySrc = GetParam().mUsageCopySrc; bool usageCopySrc = false) {
// If we do this test with a CopyWithinSameTexture, it will need to have usageCopySrc in the
// public usage of the texture as it will later use a CopyTextureToBuffer, that needs the
// public usage of it.
DAWN_TEST_UNSUPPORTED_IF(!usageCopySrc && copyWithinSameTexture);
ASSERT_EQ(srcSpec.format, dstSpec.format);
const wgpu::TextureFormat format = srcSpec.format; const wgpu::TextureFormat format = srcSpec.format;
wgpu::TextureDescriptor srcDescriptor; wgpu::TextureDescriptor srcDescriptor;
@ -375,7 +365,7 @@ class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParam
} else { } else {
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc; internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
} }
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor); wgpu::Texture srcTexture = this->device.CreateTexture(&srcDescriptor);
wgpu::Texture dstTexture; wgpu::Texture dstTexture;
if (copyWithinSameTexture) { if (copyWithinSameTexture) {
@ -385,10 +375,10 @@ class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParam
dstDescriptor.dimension = dstDimension; dstDescriptor.dimension = dstDimension;
dstDescriptor.size = dstSpec.textureSize; dstDescriptor.size = dstSpec.textureSize;
dstDescriptor.sampleCount = 1; dstDescriptor.sampleCount = 1;
dstDescriptor.format = format; dstDescriptor.format = dstSpec.format;
dstDescriptor.mipLevelCount = dstSpec.levelCount; dstDescriptor.mipLevelCount = dstSpec.levelCount;
dstDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst; dstDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
dstTexture = device.CreateTexture(&dstDescriptor); dstTexture = this->device.CreateTexture(&dstDescriptor);
} }
// Create an upload buffer and use it to completely populate the subresources of the src // Create an upload buffer and use it to completely populate the subresources of the src
@ -409,12 +399,12 @@ class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParam
srcTexture, srcSpec.copyLevel, {0, 0, srcSpec.copyOrigin.z}); srcTexture, srcSpec.copyLevel, {0, 0, srcSpec.copyOrigin.z});
wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout( wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(
0, srcDataCopyLayout.bytesPerRow, srcDataCopyLayout.rowsPerImage); 0, srcDataCopyLayout.bytesPerRow, srcDataCopyLayout.rowsPerImage);
queue.WriteTexture(&imageCopyTexture, srcTextureCopyData.data(), this->queue.WriteTexture(&imageCopyTexture, srcTextureCopyData.data(),
srcDataCopyLayout.byteLength, &textureDataLayout, srcDataCopyLayout.byteLength, &textureDataLayout,
&srcDataCopyLayout.mipSize); &srcDataCopyLayout.mipSize);
} }
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = this->device.CreateCommandEncoder();
// Perform the texture to texture copy // Perform the texture to texture copy
wgpu::ImageCopyTexture srcImageCopyTexture = wgpu::ImageCopyTexture srcImageCopyTexture =
@ -442,7 +432,7 @@ class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParam
wgpu::BufferDescriptor outputBufferDescriptor; wgpu::BufferDescriptor outputBufferDescriptor;
outputBufferDescriptor.size = dstDataCopyLayout.byteLength; outputBufferDescriptor.size = dstDataCopyLayout.byteLength;
outputBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; outputBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
wgpu::Buffer outputBuffer = device.CreateBuffer(&outputBufferDescriptor); wgpu::Buffer outputBuffer = this->device.CreateBuffer(&outputBufferDescriptor);
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format); const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
const uint32_t expectedDstDataOffset = dstSpec.copyOrigin.x * bytesPerTexel + const uint32_t expectedDstDataOffset = dstSpec.copyOrigin.x * bytesPerTexel +
dstSpec.copyOrigin.y * dstDataCopyLayout.bytesPerRow; dstSpec.copyOrigin.y * dstDataCopyLayout.bytesPerRow;
@ -452,7 +442,7 @@ class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParam
encoder.CopyTextureToBuffer(&dstImageCopyTexture, &outputImageCopyBuffer, &copySize); encoder.CopyTextureToBuffer(&dstImageCopyTexture, &outputImageCopyBuffer, &copySize);
wgpu::CommandBuffer commands = encoder.Finish(); wgpu::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands); this->queue.Submit(1, &commands);
// Validate if the data in outputBuffer is what we expected, including the untouched data // Validate if the data in outputBuffer is what we expected, including the untouched data
// outside of the copy. // outside of the copy.
@ -504,6 +494,67 @@ class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParam
} }
}; };
class CopyTests_T2T : public CopyTests_T2TBase<DawnTestWithParams<CopyTestsParams>> {
protected:
void DoTest(const TextureSpec& srcSpec,
const TextureSpec& dstSpec,
const wgpu::Extent3D& copySize,
bool copyWithinSameTexture = false,
wgpu::TextureDimension dimension = wgpu::TextureDimension::e2D) {
DoTest(srcSpec, dstSpec, copySize, dimension, dimension, copyWithinSameTexture);
}
void DoTest(const TextureSpec& srcSpec,
const TextureSpec& dstSpec,
const wgpu::Extent3D& copySize,
wgpu::TextureDimension srcDimension,
wgpu::TextureDimension dstDimension,
bool copyWithinSameTexture = false) {
const bool usageCopySrc = GetParam().mUsageCopySrc;
// If we do this test with a CopyWithinSameTexture, it will need to have usageCopySrc in the
// public usage of the texture as it will later use a CopyTextureToBuffer, that needs the
// public usage of it.
DAWN_TEST_UNSUPPORTED_IF(!usageCopySrc && copyWithinSameTexture);
ASSERT_EQ(srcSpec.format, dstSpec.format);
CopyTests_T2TBase<DawnTestWithParams<CopyTestsParams>>::DoTest(
srcSpec, dstSpec, copySize, srcDimension, dstDimension, copyWithinSameTexture,
usageCopySrc);
}
};
class CopyTests_Formats : public CopyTests_T2TBase<DawnTestWithParams<SrcColorFormatParams>> {
protected:
// Texture format is compatible and could be copied to each other if the only diff is srgb-ness.
wgpu::TextureFormat GetCopyCompatibleFormat(wgpu::TextureFormat format) {
switch (format) {
case wgpu::TextureFormat::RGBA8Unorm:
return wgpu::TextureFormat::RGBA8UnormSrgb;
case wgpu::TextureFormat::RGBA8UnormSrgb:
return wgpu::TextureFormat::RGBA8Unorm;
case wgpu::TextureFormat::BGRA8Unorm:
return wgpu::TextureFormat::BGRA8UnormSrgb;
case wgpu::TextureFormat::BGRA8UnormSrgb:
return wgpu::TextureFormat::BGRA8Unorm;
default:
UNREACHABLE();
}
}
void DoTest(TextureSpec srcSpec,
TextureSpec dstSpec,
const wgpu::Extent3D& copySize,
wgpu::TextureDimension srcDimension = wgpu::TextureDimension::e2D,
wgpu::TextureDimension dstDimension = wgpu::TextureDimension::e2D) {
srcSpec.format = GetParam().mSrcColorFormat;
dstSpec.format = GetCopyCompatibleFormat(srcSpec.format);
CopyTests_T2TBase<DawnTestWithParams<SrcColorFormatParams>>::DoTest(
srcSpec, dstSpec, copySize, srcDimension, dstDimension);
}
};
class CopyTests_B2B : public DawnTest { class CopyTests_B2B : public DawnTest {
protected: protected:
// This is the same signature as CopyBufferToBuffer except that the buffers are replaced by // This is the same signature as CopyBufferToBuffer except that the buffers are replaced by
@ -2409,6 +2460,27 @@ DAWN_INSTANTIATE_TEST_P(CopyTests_T2T,
MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()}, MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()},
{true, false}); {true, false});
// Test copying between textures that have srgb compatible texture formats;
TEST_P(CopyTests_Formats, SrgbCompatibility) {
// Skip backends because which fails to support *-srgb formats
// and bgra* formats.
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
constexpr uint32_t kWidth = 256;
constexpr uint32_t kHeight = 128;
TextureSpec textureSpec;
textureSpec.textureSize = {kWidth, kHeight, 1};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
}
DAWN_INSTANTIATE_TEST_P(CopyTests_Formats,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
{wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::RGBA8UnormSrgb,
wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::BGRA8UnormSrgb});
static constexpr uint64_t kSmallBufferSize = 4; static constexpr uint64_t kSmallBufferSize = 4;
static constexpr uint64_t kLargeBufferSize = 1 << 16; static constexpr uint64_t kLargeBufferSize = 1 << 16;

View File

@ -1646,6 +1646,21 @@ class CopyCommandTest_T2T : public CopyCommandTest {
descriptor.requiredFeaturesCount = 2; descriptor.requiredFeaturesCount = 2;
return adapter.CreateDevice(&descriptor); return adapter.CreateDevice(&descriptor);
} }
wgpu::TextureFormat GetCopyCompatibleFormat(wgpu::TextureFormat format) {
switch (format) {
case wgpu::TextureFormat::BGRA8Unorm:
return wgpu::TextureFormat::BGRA8UnormSrgb;
case wgpu::TextureFormat::BGRA8UnormSrgb:
return wgpu::TextureFormat::BGRA8Unorm;
case wgpu::TextureFormat::RGBA8Unorm:
return wgpu::TextureFormat::RGBA8UnormSrgb;
case wgpu::TextureFormat::RGBA8UnormSrgb:
return wgpu::TextureFormat::RGBA8Unorm;
default:
UNREACHABLE();
}
}
}; };
TEST_F(CopyCommandTest_T2T, Success) { TEST_F(CopyCommandTest_T2T, Success) {
@ -1892,6 +1907,23 @@ TEST_F(CopyCommandTest_T2T, FormatsMismatch) {
{0, 0, 1}); {0, 0, 1});
} }
// Test copying between textures that have srgb compatible texture formats;
TEST_F(CopyCommandTest_T2T, SrgbFormatsCompatibility) {
for (wgpu::TextureFormat srcTextureFormat :
{wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::BGRA8UnormSrgb,
wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::RGBA8UnormSrgb}) {
wgpu::TextureFormat dstTextureFormat = GetCopyCompatibleFormat(srcTextureFormat);
wgpu::Texture source =
Create2DTexture(16, 16, 5, 2, srcTextureFormat, wgpu::TextureUsage::CopySrc);
wgpu::Texture destination =
Create2DTexture(16, 16, 5, 2, dstTextureFormat, wgpu::TextureUsage::CopyDst);
// Failure when formats don't match
TestT2TCopy(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0, {0, 0, 0},
{0, 0, 1});
}
}
TEST_F(CopyCommandTest_T2T, MultisampledCopies) { TEST_F(CopyCommandTest_T2T, MultisampledCopies) {
wgpu::Texture sourceMultiSampled1x = Create2DTexture( wgpu::Texture sourceMultiSampled1x = Create2DTexture(
16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc, 1); 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc, 1);
@ -2112,6 +2144,97 @@ class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
uint32_t height = utils::GetTextureFormatBlockHeight(format) * 4; uint32_t height = utils::GetTextureFormatBlockHeight(format) * 4;
return Create2DTexture(format, 1, width, height); return Create2DTexture(format, 1, width, height);
} }
wgpu::TextureFormat GetCopyCompatibleFormat(wgpu::TextureFormat format) {
switch (format) {
case wgpu::TextureFormat::BC1RGBAUnorm:
return wgpu::TextureFormat::BC1RGBAUnormSrgb;
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
return wgpu::TextureFormat::BC1RGBAUnorm;
case wgpu::TextureFormat::BC2RGBAUnorm:
return wgpu::TextureFormat::BC2RGBAUnormSrgb;
case wgpu::TextureFormat::BC2RGBAUnormSrgb:
return wgpu::TextureFormat::BC2RGBAUnorm;
case wgpu::TextureFormat::BC3RGBAUnorm:
return wgpu::TextureFormat::BC3RGBAUnormSrgb;
case wgpu::TextureFormat::BC3RGBAUnormSrgb:
return wgpu::TextureFormat::BC3RGBAUnorm;
case wgpu::TextureFormat::BC7RGBAUnorm:
return wgpu::TextureFormat::BC7RGBAUnormSrgb;
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return wgpu::TextureFormat::BC7RGBAUnorm;
case wgpu::TextureFormat::ETC2RGB8Unorm:
return wgpu::TextureFormat::ETC2RGB8UnormSrgb;
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
return wgpu::TextureFormat::ETC2RGB8Unorm;
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
return wgpu::TextureFormat::ETC2RGB8A1UnormSrgb;
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
return wgpu::TextureFormat::ETC2RGB8A1Unorm;
case wgpu::TextureFormat::ETC2RGBA8Unorm:
return wgpu::TextureFormat::ETC2RGBA8UnormSrgb;
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
return wgpu::TextureFormat::ETC2RGBA8Unorm;
case wgpu::TextureFormat::ASTC4x4Unorm:
return wgpu::TextureFormat::ASTC4x4UnormSrgb;
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
return wgpu::TextureFormat::ASTC4x4Unorm;
case wgpu::TextureFormat::ASTC5x4Unorm:
return wgpu::TextureFormat::ASTC5x4UnormSrgb;
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
return wgpu::TextureFormat::ASTC5x4Unorm;
case wgpu::TextureFormat::ASTC5x5Unorm:
return wgpu::TextureFormat::ASTC5x5UnormSrgb;
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
return wgpu::TextureFormat::ASTC5x5Unorm;
case wgpu::TextureFormat::ASTC6x5Unorm:
return wgpu::TextureFormat::ASTC6x5UnormSrgb;
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
return wgpu::TextureFormat::ASTC6x5Unorm;
case wgpu::TextureFormat::ASTC6x6Unorm:
return wgpu::TextureFormat::ASTC6x6UnormSrgb;
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
return wgpu::TextureFormat::ASTC6x6Unorm;
case wgpu::TextureFormat::ASTC8x5Unorm:
return wgpu::TextureFormat::ASTC8x5UnormSrgb;
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
return wgpu::TextureFormat::ASTC8x5Unorm;
case wgpu::TextureFormat::ASTC8x6Unorm:
return wgpu::TextureFormat::ASTC8x6UnormSrgb;
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
return wgpu::TextureFormat::ASTC8x6Unorm;
case wgpu::TextureFormat::ASTC8x8Unorm:
return wgpu::TextureFormat::ASTC8x8UnormSrgb;
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
return wgpu::TextureFormat::ASTC8x8Unorm;
case wgpu::TextureFormat::ASTC10x5Unorm:
return wgpu::TextureFormat::ASTC10x5UnormSrgb;
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
return wgpu::TextureFormat::ASTC10x5Unorm;
case wgpu::TextureFormat::ASTC10x6Unorm:
return wgpu::TextureFormat::ASTC10x6UnormSrgb;
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
return wgpu::TextureFormat::ASTC10x6Unorm;
case wgpu::TextureFormat::ASTC10x8Unorm:
return wgpu::TextureFormat::ASTC10x8UnormSrgb;
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
return wgpu::TextureFormat::ASTC10x8Unorm;
case wgpu::TextureFormat::ASTC10x10Unorm:
return wgpu::TextureFormat::ASTC10x10UnormSrgb;
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
return wgpu::TextureFormat::ASTC10x10Unorm;
case wgpu::TextureFormat::ASTC12x10Unorm:
return wgpu::TextureFormat::ASTC12x10UnormSrgb;
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
return wgpu::TextureFormat::ASTC12x10Unorm;
case wgpu::TextureFormat::ASTC12x12Unorm:
return wgpu::TextureFormat::ASTC12x12UnormSrgb;
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return wgpu::TextureFormat::ASTC12x12Unorm;
default:
UNREACHABLE();
}
}
}; };
// Tests to verify that bufferOffset must be a multiple of the compressed texture blocks in bytes // Tests to verify that bufferOffset must be a multiple of the compressed texture blocks in bytes
@ -2358,6 +2481,48 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, CopyToMultipleArrayLayers) {
} }
} }
// Test copying between textures that have srgb compatible texture formats;
TEST_F(CopyCommandTest_CompressedTextureFormats, SrgbFormatCompatibility) {
constexpr std::array<wgpu::TextureFormat, 42> srcFormats = {
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb,
wgpu::TextureFormat::ETC2RGB8Unorm, wgpu::TextureFormat::ETC2RGB8UnormSrgb,
wgpu::TextureFormat::ETC2RGB8A1Unorm, wgpu::TextureFormat::ETC2RGB8A1UnormSrgb,
wgpu::TextureFormat::ETC2RGBA8Unorm, wgpu::TextureFormat::ETC2RGBA8UnormSrgb,
wgpu::TextureFormat::ASTC4x4Unorm, wgpu::TextureFormat::ASTC4x4UnormSrgb,
wgpu::TextureFormat::ASTC5x4Unorm, wgpu::TextureFormat::ASTC5x4UnormSrgb,
wgpu::TextureFormat::ASTC5x5Unorm, wgpu::TextureFormat::ASTC5x5UnormSrgb,
wgpu::TextureFormat::ASTC6x5Unorm, wgpu::TextureFormat::ASTC6x5UnormSrgb,
wgpu::TextureFormat::ASTC6x6Unorm, wgpu::TextureFormat::ASTC6x6UnormSrgb,
wgpu::TextureFormat::ASTC8x5Unorm, wgpu::TextureFormat::ASTC8x5UnormSrgb,
wgpu::TextureFormat::ASTC8x6Unorm, wgpu::TextureFormat::ASTC8x6UnormSrgb,
wgpu::TextureFormat::ASTC8x8Unorm, wgpu::TextureFormat::ASTC8x8UnormSrgb,
wgpu::TextureFormat::ASTC10x5Unorm, wgpu::TextureFormat::ASTC10x5UnormSrgb,
wgpu::TextureFormat::ASTC10x6Unorm, wgpu::TextureFormat::ASTC10x6UnormSrgb,
wgpu::TextureFormat::ASTC10x8Unorm, wgpu::TextureFormat::ASTC10x8UnormSrgb,
wgpu::TextureFormat::ASTC10x10Unorm, wgpu::TextureFormat::ASTC10x10UnormSrgb,
wgpu::TextureFormat::ASTC12x10Unorm, wgpu::TextureFormat::ASTC12x10UnormSrgb,
wgpu::TextureFormat::ASTC12x12Unorm, wgpu::TextureFormat::ASTC12x12UnormSrgb};
constexpr uint32_t kBlockPerDim = 2;
constexpr uint32_t kMipmapLevels = 1;
for (wgpu::TextureFormat srcFormat : srcFormats) {
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(srcFormat);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(srcFormat);
uint32_t testWidth = blockWidth * kBlockPerDim;
uint32_t testHeight = blockHeight * kBlockPerDim;
wgpu::Texture texture = Create2DTexture(srcFormat, kMipmapLevels, testWidth, testHeight);
wgpu::Texture texture2 = Create2DTexture(GetCopyCompatibleFormat(srcFormat), kMipmapLevels,
testWidth, testHeight);
wgpu::Extent3D extent3D = {testWidth, testHeight, 1};
TestBothT2TCopies(utils::Expectation::Success, texture, 0, {0, 0, 0}, texture2, 0,
{0, 0, 0}, extent3D);
}
}
class CopyCommandTest_ClearBuffer : public CopyCommandTest {}; class CopyCommandTest_ClearBuffer : public CopyCommandTest {};
TEST_F(CopyCommandTest_ClearBuffer, Success) { TEST_F(CopyCommandTest_ClearBuffer, Success) {