Add MetalRenderR8RG8UnormSmallMipToTempTexture workaround

This workaround replaces the toggle that forbids creating mipmapped
R8Unorm and RG8Unorm textures on Metal. Instead it adds a Metal render
pass workaround that renders to a temporary texture under certain
conditions, then copies back to the correct mip level.

The texture lazy-clearing code is also changed to use the helper that
does workarounds for Metal render passes.

A test is added that triggers the issue with a small amount of code, but
more extensive coverage is left to the CTS. For example texture_zero
tests caught multiple issues during the creation of this CL.

Bug: dawn:1071

Change-Id: I7ef1151524e71e5a9a8e8f5205d9b554bee438b3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87864
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Corentin Wallez 2022-04-28 19:00:53 +00:00 committed by Dawn LUCI CQ
parent 01004b7732
commit bd8de5d2a4
9 changed files with 272 additions and 123 deletions

View File

@ -394,13 +394,6 @@ namespace dawn::native {
"https://crbug.com/dawn/838: Stencil textures with more than one mip level are "
"disabled on Metal.");
DAWN_INVALID_IF(
device->IsToggleEnabled(Toggle::DisableR8RG8Mipmaps) && descriptor->mipLevelCount > 1 &&
(descriptor->format == wgpu::TextureFormat::R8Unorm ||
descriptor->format == wgpu::TextureFormat::RG8Unorm),
"https://crbug.com/dawn/1071: r8unorm and rg8unorm textures with more than one mip "
"level are disabled on Metal.");
return {};
}

View File

@ -231,11 +231,6 @@ namespace dawn::native {
"Enables calls to SetLabel to be forwarded to backend-specific APIs that label "
"objects.",
"https://crbug.com/dawn/840"}},
{Toggle::DisableR8RG8Mipmaps,
{"disable_r8_rg8_mipmaps",
"Disables mipmaps for r8unorm and rg8unorm textures, which are known on some drivers "
"to not clear correctly.",
"https://crbug.com/dawn/1071"}},
{Toggle::UsePlaceholderFragmentInVertexOnlyPipeline,
{"use_placeholder_fragment_in_vertex_only_pipeline",
"Use a placeholder empty fragment shader in vertex only render pipeline. This toggle "
@ -272,7 +267,14 @@ namespace dawn::native {
"it via split the copy operation into two copies, in order to make B2T/T2B copy "
"being done correctly on D3D12.",
"https://crbug.com/dawn/1289"}},
{Toggle::MetalRenderR8RG8UnormSmallMipToTempTexture,
{"metal_render_r8_rg8_unorm_small_mip_to_temp_texture",
"Metal Intel devices have issues with r8unorm and rg8unorm textures where rendering "
"to small mips (level >= 2) doesn't work correctly. Workaround this issue by "
"detecting this case and rendering to a temporary texture instead (with copies "
"before "
"and after if needed).",
"https://crbug.com/dawn/1071"}},
// Comment to separate the }} so it is clearer what to copy-paste to add a toggle.
}};
} // anonymous namespace

View File

@ -62,13 +62,13 @@ namespace dawn::native {
DisableWorkgroupInit,
DisableSymbolRenaming,
UseUserDefinedLabelsInBackend,
DisableR8RG8Mipmaps,
UsePlaceholderFragmentInVertexOnlyPipeline,
FxcOptimizations,
RecordDetailedTimingInTraceEvents,
DisableTimestampQueryConversion,
VulkanUseZeroInitializeWorkgroupMemoryExtension,
D3D12SplitBufferTextureCopyForRowsPerImagePaddings,
MetalRenderR8RG8UnormSmallMipToTempTexture,
EnumCount,
InvalidEnum = EnumCount,

View File

@ -210,10 +210,10 @@ namespace dawn::native::metal {
SetToggle(Toggle::MetalUseSharedModeForCounterSampleBuffer, useSharedMode);
}
// TODO(crbug.com/dawn/1071): r8unorm and rg8unorm textures with multiple mip levels don't
// clear properly on Intel Macs.
// Rendering R8Unorm and RG8Unorm to small mip doesn't work properly on Intel.
// TODO(crbug.com/dawn/1071): Tighten the workaround when this issue is fixed.
if (gpu_info::IsIntel(vendorId)) {
SetToggle(Toggle::DisableR8RG8Mipmaps, true);
SetToggle(Toggle::MetalRenderR8RG8UnormSmallMipToTempTexture, true);
}
// On some Intel GPU vertex only render pipeline get wrong depth result if no fragment

View File

@ -875,8 +875,8 @@ namespace dawn::native::metal {
}
}
commandContext->BeginRender(descriptor);
commandContext->EndRender();
DAWN_TRY(EncodeEmptyMetalRenderPass(device, commandContext, descriptor,
GetMipLevelVirtualSize(level)));
}
}
} else {
@ -923,16 +923,18 @@ namespace dawn::native::metal {
if (attachment == kMaxColorAttachments) {
attachment = 0;
commandContext->BeginRender(descriptor.Get());
commandContext->EndRender();
DAWN_TRY(EncodeEmptyMetalRenderPass(device, commandContext,
descriptor.Get(),
GetMipLevelVirtualSize(level)));
descriptor = nullptr;
}
}
}
if (descriptor != nullptr) {
commandContext->BeginRender(descriptor.Get());
commandContext->EndRender();
DAWN_TRY(EncodeEmptyMetalRenderPass(device, commandContext,
descriptor.Get(),
GetMipLevelVirtualSize(level)));
}
}
}

View File

@ -102,6 +102,11 @@ namespace dawn::native::metal {
uint32_t height,
EncodeInsideRenderPass encodeInside);
MaybeError EncodeEmptyMetalRenderPass(Device* device,
CommandRecordingContext* commandContext,
MTLRenderPassDescriptor* mtlRenderPass,
Extent3D size);
} // namespace dawn::native::metal
#endif // SRC_DAWN_NATIVE_METAL_UTILSMETAL_H_

View File

@ -13,15 +13,126 @@
// limitations under the License.
#include "dawn/native/metal/UtilsMetal.h"
#include "dawn/common/Assert.h"
#include "dawn/native/CommandBuffer.h"
#include "dawn/native/Pipeline.h"
#include "dawn/native/ShaderModule.h"
#include "dawn/common/Assert.h"
namespace dawn::native::metal {
namespace {
// A helper struct to track state while doing workarounds for Metal render passes. It
// contains a temporary texture and information about the attachment it replaces.
// Helper methods encode copies between the two textures.
struct SavedMetalAttachment {
id<MTLTexture> texture = nil;
NSUInteger level;
NSUInteger slice;
NSPRef<id<MTLTexture>> temporary;
void CopyFromTemporaryToAttachment(CommandRecordingContext* commandContext) {
[commandContext->EnsureBlit()
copyFromTexture:temporary.Get()
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake([temporary.Get() width], [temporary.Get() height],
1)
toTexture:texture
destinationSlice:slice
destinationLevel:level
destinationOrigin:MTLOriginMake(0, 0, 0)];
}
void CopyFromAttachmentToTemporary(CommandRecordingContext* commandContext) {
[commandContext->EnsureBlit()
copyFromTexture:texture
sourceSlice:slice
sourceLevel:level
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake([temporary.Get() width], [temporary.Get() height],
1)
toTexture:temporary.Get()
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(0, 0, 0)];
}
};
// Common code between both kinds of attachments swaps.
ResultOrError<SavedMetalAttachment> SaveAttachmentCreateTemporary(
Device* device,
id<MTLTexture> attachmentTexture,
NSUInteger attachmentLevel,
NSUInteger attachmentSlice) {
// Save the attachment.
SavedMetalAttachment result;
result.texture = attachmentTexture;
result.level = attachmentLevel;
result.slice = attachmentSlice;
// Create the temporary texture.
NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
mtlDesc.textureType = MTLTextureType2D;
mtlDesc.usage = MTLTextureUsageRenderTarget;
mtlDesc.pixelFormat = [result.texture pixelFormat];
mtlDesc.width = std::max([result.texture width] >> attachmentLevel, NSUInteger(1));
mtlDesc.height = std::max([result.texture height] >> attachmentLevel, NSUInteger(1));
mtlDesc.depth = 1;
mtlDesc.mipmapLevelCount = 1;
mtlDesc.arrayLength = 1;
mtlDesc.storageMode = MTLStorageModePrivate;
mtlDesc.sampleCount = [result.texture sampleCount];
result.temporary =
AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc]);
if (result.temporary == nil) {
return DAWN_OUT_OF_MEMORY_ERROR("Allocation of temporary texture failed.");
}
return result;
}
// Patches the render pass attachment to replace it with a temporary texture. Returns a
// SavedMetalAttachment that can be used to easily copy between the original attachment and
// the temporary.
ResultOrError<SavedMetalAttachment> PatchAttachmentWithTemporary(
Device* device,
MTLRenderPassAttachmentDescriptor* attachment) {
SavedMetalAttachment result;
DAWN_TRY_ASSIGN(
result, SaveAttachmentCreateTemporary(device, attachment.texture, attachment.level,
attachment.slice));
// Replace the attachment with the temporary
attachment.texture = result.temporary.Get();
attachment.level = 0;
attachment.slice = 0;
return result;
}
// Same as PatchAttachmentWithTemporary but for the resolve attachment.
ResultOrError<SavedMetalAttachment> PatchResolveAttachmentWithTemporary(
Device* device,
MTLRenderPassAttachmentDescriptor* attachment) {
SavedMetalAttachment result;
DAWN_TRY_ASSIGN(result, SaveAttachmentCreateTemporary(device, attachment.resolveTexture,
attachment.resolveLevel,
attachment.resolveSlice));
// Replace the resolve attachment with the tempoary.
attachment.resolveTexture = result.temporary.Get();
attachment.resolveLevel = 0;
attachment.resolveSlice = 0;
return result;
}
// Helper function for Toggle EmulateStoreAndMSAAResolve
void ResolveInAnotherRenderPass(
CommandRecordingContext* commandContext,
@ -52,52 +163,6 @@ namespace dawn::native::metal {
commandContext->BeginRender(mtlRenderPassForResolve);
commandContext->EndRender();
}
// Helper functions for Toggle AlwaysResolveIntoZeroLevelAndLayer
ResultOrError<NSPRef<id<MTLTexture>>> CreateResolveTextureForWorkaround(
Device* device,
MTLPixelFormat mtlFormat,
uint32_t width,
uint32_t height) {
NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
mtlDesc.textureType = MTLTextureType2D;
mtlDesc.usage = MTLTextureUsageRenderTarget;
mtlDesc.pixelFormat = mtlFormat;
mtlDesc.width = width;
mtlDesc.height = height;
mtlDesc.depth = 1;
mtlDesc.mipmapLevelCount = 1;
mtlDesc.arrayLength = 1;
mtlDesc.storageMode = MTLStorageModePrivate;
mtlDesc.sampleCount = 1;
id<MTLTexture> texture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc];
if (texture == nil) {
return DAWN_OUT_OF_MEMORY_ERROR("Allocation of temporary texture failed.");
}
return AcquireNSPRef(texture);
}
void CopyIntoTrueResolveTarget(CommandRecordingContext* commandContext,
id<MTLTexture> mtlTrueResolveTexture,
uint32_t trueResolveLevel,
uint32_t trueResolveSlice,
id<MTLTexture> temporaryResolveTexture,
uint32_t width,
uint32_t height) {
[commandContext->EnsureBlit() copyFromTexture:temporaryResolveTexture
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(width, height, 1)
toTexture:mtlTrueResolveTexture
destinationSlice:trueResolveSlice
destinationLevel:trueResolveLevel
destinationOrigin:MTLOriginMake(0, 0, 0)];
}
} // anonymous namespace
MTLCompareFunction ToMetalCompareFunction(wgpu::CompareFunction compareFunction) {
@ -370,18 +435,16 @@ namespace dawn::native::metal {
uint32_t width,
uint32_t height,
EncodeInsideRenderPass encodeInside) {
// This function handles multiple workarounds. Because some cases requires multiple
// workarounds to happen at the same time, it handles workarounds one by one and calls
// itself recursively to handle the next workaround if needed.
// Handle Toggle AlwaysResolveIntoZeroLevelAndLayer. We must handle this before applying
// the store + MSAA resolve workaround, otherwise this toggle will never be handled because
// the resolve texture is removed when applying the store + MSAA resolve workaround.
if (device->IsToggleEnabled(Toggle::AlwaysResolveIntoZeroLevelAndLayer)) {
std::array<id<MTLTexture>, kMaxColorAttachments> trueResolveTextures = {};
std::array<uint32_t, kMaxColorAttachments> trueResolveLevels = {};
std::array<uint32_t, kMaxColorAttachments> trueResolveSlices = {};
// Use temporary resolve texture on the resolve targets with non-zero resolveLevel or
// resolveSlice.
bool useTemporaryResolveTexture = false;
std::array<NSPRef<id<MTLTexture>>, kMaxColorAttachments> temporaryResolveTextures = {};
std::array<SavedMetalAttachment, kMaxColorAttachments> trueResolveAttachments = {};
bool workaroundUsed = false;
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
if (mtlRenderPass.colorAttachments[i].resolveTexture == nullptr) {
continue;
@ -392,42 +455,80 @@ namespace dawn::native::metal {
continue;
}
trueResolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;
trueResolveLevels[i] = mtlRenderPass.colorAttachments[i].resolveLevel;
trueResolveSlices[i] = mtlRenderPass.colorAttachments[i].resolveSlice;
const MTLPixelFormat mtlFormat = trueResolveTextures[i].pixelFormat;
DAWN_TRY_ASSIGN(temporaryResolveTextures[i], CreateResolveTextureForWorkaround(
device, mtlFormat, width, height));
mtlRenderPass.colorAttachments[i].resolveTexture =
temporaryResolveTextures[i].Get();
mtlRenderPass.colorAttachments[i].resolveLevel = 0;
mtlRenderPass.colorAttachments[i].resolveSlice = 0;
useTemporaryResolveTexture = true;
DAWN_TRY_ASSIGN(
trueResolveAttachments[i],
PatchResolveAttachmentWithTemporary(device, mtlRenderPass.colorAttachments[i]));
workaroundUsed = true;
}
// If we need to use a temporary resolve texture we need to copy the result of MSAA
// resolve back to the true resolve targets.
if (useTemporaryResolveTexture) {
if (workaroundUsed) {
DAWN_TRY(EncodeMetalRenderPass(device, commandContext, mtlRenderPass, width, height,
std::move(encodeInside)));
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
if (trueResolveTextures[i] == nullptr) {
if (trueResolveAttachments[i].texture == nullptr) {
continue;
}
ASSERT(temporaryResolveTextures[i] != nullptr);
CopyIntoTrueResolveTarget(commandContext, trueResolveTextures[i],
trueResolveLevels[i], trueResolveSlices[i],
temporaryResolveTextures[i].Get(), width, height);
trueResolveAttachments[i].CopyFromTemporaryToAttachment(commandContext);
}
return {};
}
}
// Handles the workaround for r8unorm rg8unorm mipmap rendering being broken on some
// devices. Render to a temporary texture instead and then copy back to the attachment.
if (device->IsToggleEnabled(Toggle::MetalRenderR8RG8UnormSmallMipToTempTexture)) {
std::array<SavedMetalAttachment, kMaxColorAttachments> originalAttachments;
bool workaroundUsed = false;
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
if (mtlRenderPass.colorAttachments[i].texture == nullptr) {
continue;
}
if ([mtlRenderPass.colorAttachments[i].texture pixelFormat] !=
MTLPixelFormatR8Unorm &&
[mtlRenderPass.colorAttachments[i].texture pixelFormat] !=
MTLPixelFormatRG8Unorm) {
continue;
}
if (mtlRenderPass.colorAttachments[i].level < 2) {
continue;
}
DAWN_TRY_ASSIGN(
originalAttachments[i],
PatchAttachmentWithTemporary(device, mtlRenderPass.colorAttachments[i]));
workaroundUsed = true;
if (mtlRenderPass.colorAttachments[i].loadAction == MTLLoadActionLoad) {
originalAttachments[i].CopyFromAttachmentToTemporary(commandContext);
}
}
if (workaroundUsed) {
DAWN_TRY(EncodeMetalRenderPass(device, commandContext, mtlRenderPass, width, height,
std::move(encodeInside)));
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
if (originalAttachments[i].texture == nullptr) {
continue;
}
originalAttachments[i].CopyFromTemporaryToAttachment(commandContext);
}
return {};
}
}
// Handle Store + MSAA resolve workaround (Toggle EmulateStoreAndMSAAResolve).
// Done after the workarounds that modify the non-resolve attachments so that
// ResolveInAnotherRenderPass uses the temporary attachments if needed instead of the
// original ones.
if (device->IsToggleEnabled(Toggle::EmulateStoreAndMSAAResolve)) {
bool hasStoreAndMSAAResolve = false;
@ -454,8 +555,19 @@ namespace dawn::native::metal {
}
}
// No (more) workarounds needed! We can finally encode the actual render pass.
commandContext->EndBlit();
DAWN_TRY(encodeInside(commandContext->BeginRender(mtlRenderPass)));
commandContext->EndRender();
return {};
}
MaybeError EncodeEmptyMetalRenderPass(Device* device,
CommandRecordingContext* commandContext,
MTLRenderPassDescriptor* mtlRenderPass,
Extent3D size) {
return EncodeMetalRenderPass(device, commandContext, mtlRenderPass, size.width, size.height,
[&](id<MTLRenderCommandEncoder>) -> MaybeError { return {}; });
}
} // namespace dawn::native::metal

View File

@ -163,6 +163,8 @@ TEST_P(RenderPassTest, NoCorrespondingFragmentShaderOutputs) {
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderTarget, kRTSize - 1, 1);
}
class RenderPassTest_RegressionDawn1071 : public RenderPassTest {};
DAWN_INSTANTIATE_TEST(RenderPassTest,
D3D12Backend(),
D3D12Backend({}, {"use_d3d12_render_pass"}),
@ -170,3 +172,61 @@ DAWN_INSTANTIATE_TEST(RenderPassTest,
OpenGLBackend(),
OpenGLESBackend(),
VulkanBackend());
// Test that clearing the lower mips of an R8Unorm texture works. This is a regression test for
// dawn:1071 where Intel Metal devices fail to do that correctly, requiring a workaround.
TEST_P(RenderPassTest_RegressionDawn1071, ClearLowestMipOfR8Unorm) {
const uint32_t kLastMipLevel = 2;
// Create the texture and buffer used for readback.
wgpu::TextureDescriptor texDesc;
texDesc.format = wgpu::TextureFormat::R8Unorm;
texDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
texDesc.size = {32, 32};
texDesc.mipLevelCount = kLastMipLevel + 1;
wgpu::Texture tex = device.CreateTexture(&texDesc);
wgpu::BufferDescriptor bufDesc;
bufDesc.size = 4;
bufDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buf = device.CreateBuffer(&bufDesc);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
// Clear the texture with a render pass.
{
wgpu::TextureViewDescriptor viewDesc;
viewDesc.baseMipLevel = kLastMipLevel;
utils::ComboRenderPassDescriptor renderPass({tex.CreateView(&viewDesc)});
renderPass.cColorAttachments[0].clearValue = {1.0f, 0.0f, 0.0f, 1.0f};
renderPass.cColorAttachments[0].loadOp = wgpu::LoadOp::Clear;
renderPass.cColorAttachments[0].storeOp = wgpu::StoreOp::Store;
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.End();
}
// Copy the texture in the buffer.
{
wgpu::Extent3D copySize = {1, 1};
wgpu::ImageCopyTexture src = utils::CreateImageCopyTexture(tex, kLastMipLevel);
wgpu::ImageCopyBuffer dst = utils::CreateImageCopyBuffer(buf);
encoder.CopyTextureToBuffer(&src, &dst, &copySize);
}
wgpu::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
// The content of the texture should be reflected in the buffer (prior to the workaround it
// would be 0s).
EXPECT_BUFFER_U8_EQ(255, buf, 0);
}
DAWN_INSTANTIATE_TEST(RenderPassTest_RegressionDawn1071,
D3D12Backend(),
MetalBackend(),
MetalBackend({"metal_render_r8_rg8_unorm_small_mip_to_temp_texture"}),
OpenGLBackend(),
OpenGLESBackend(),
VulkanBackend());

View File

@ -77,13 +77,6 @@ crbug.com/dawn/1111 [ intel-0x5912 ] webgpu:shader,execution,zero_init:compute,z
crbug.com/dawn/1111 [ intel-0x5912 ] webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=1 [ Failure ]
crbug.com/dawn/1111 [ intel-0x5912 ] webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[8,8,2];batch__=1 [ Failure ]
################################################################################
# webgpu:api,operation,command_buffer,image_copy:mip_levels
# Partial failures on all platforms
# KEEP
################################################################################
crbug.com/dawn/0000 webgpu:api,operation,command_buffer,image_copy:mip_levels:* [ Failure ]
################################################################################
# webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero
# Spec / CTS bugs because depth24unorm-stencil8 depth-specific format is depth24plus
@ -112,18 +105,6 @@ crbug.com/dawn/1389 [ mac ] webgpu:api,operation,resource_init,texture_zero:unin
crbug.com/dawn/1389 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="stencil8" [ Failure ]
crbug.com/dawn/1389 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="stencil8" [ Failure ]
crbug.com/dawn/1389 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="StencilTest";format="stencil8" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="r8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="r8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="r8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rg8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToTexture";format="rg8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="Sample";format="rg8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="r8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="r8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="r8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rg8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToTexture";format="rg8unorm" [ Failure ]
crbug.com/dawn/1071 [ mac ] webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="Sample";format="rg8unorm" [ Failure ]
################################################################################
# webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero
@ -355,18 +336,12 @@ crbug.com/dawn/1325 webgpu:api,validation,attachment_compatibility:render_pass_o
################################################################################
crbug.com/dawn/0000 [ mac ] webgpu:api,operation,command_buffer,copyTextureToTexture:copy_depth_stencil:format="depth32float" [ Failure ]
crbug.com/dawn/0000 [ win ] webgpu:api,operation,render_pass,resolve:* [ Failure ]
crbug.com/dawn/0000 [ mac ] webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:colorFormat="r8unorm";* [ Failure ]
crbug.com/dawn/0000 [ mac ] webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:colorFormat="rg8unorm";* [ Failure ]
crbug.com/dawn/0000 [ win ] webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count,blend:format="rg8unorm" [ Failure ]
crbug.com/dawn/0000 [ win ] webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:indexed=true;indirect=true;drawCallTestParameter="baseVertex";* [ Failure ]
crbug.com/1236130 [ linux ] webgpu:web_platform,canvas,readbackFromWebGPUCanvas:* [ Skip ] # crashes (skip because there are very many)
crbug.com/dawn/0000 [ mac ] webgpu:web_platform,canvas,readbackFromWebGPUCanvas:* [ Failure ]
crbug.com/1309194 [ linux ] webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:* [ Skip ] # crashes (skip because there are very many)
crbug.com/1309194 [ linux ] webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:* [ Skip ] # crashes (skip because there are very many)
crbug.com/dawn/0000 [ mac ] worker_webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:colorFormat="r8unorm";storeOperation="discard" [ Failure ]
crbug.com/dawn/0000 [ mac ] worker_webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:colorFormat="r8unorm";storeOperation="store" [ Failure ]
crbug.com/dawn/0000 [ mac ] worker_webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:colorFormat="rg8unorm";storeOperation="discard" [ Failure ]
crbug.com/dawn/0000 [ mac ] worker_webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:colorFormat="rg8unorm";storeOperation="store" [ Failure ]
crbug.com/dawn/0000 [ mac ] worker_webgpu:api,operation,render_pass,storeOp:render_pass_store_op,depth_stencil_attachment_only:depthStencilFormat="stencil8";* [ Failure ]
################################################################################