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:
parent
01004b7732
commit
bd8de5d2a4
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -62,13 +62,13 @@ namespace dawn::native {
|
|||
DisableWorkgroupInit,
|
||||
DisableSymbolRenaming,
|
||||
UseUserDefinedLabelsInBackend,
|
||||
DisableR8RG8Mipmaps,
|
||||
UsePlaceholderFragmentInVertexOnlyPipeline,
|
||||
FxcOptimizations,
|
||||
RecordDetailedTimingInTraceEvents,
|
||||
DisableTimestampQueryConversion,
|
||||
VulkanUseZeroInitializeWorkgroupMemoryExtension,
|
||||
D3D12SplitBufferTextureCopyForRowsPerImagePaddings,
|
||||
MetalRenderR8RG8UnormSmallMipToTempTexture,
|
||||
|
||||
EnumCount,
|
||||
InvalidEnum = EnumCount,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ©Size);
|
||||
}
|
||||
|
||||
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());
|
||||
|
|
|
@ -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 ]
|
||||
|
||||
################################################################################
|
||||
|
|
Loading…
Reference in New Issue