Metal: Move Metal render pass workarounds to UtilsMetal
In follow-up commits these workarounds will be used in more than just the CommandBuffer but also for lazy-texture clearing. In this CL the helpers are just moved and changed to take `encodeInside` as a std::function. Bug: dawn:1071 Change-Id: Ib3b90826c89e12edca41223b3c8b5a4cfc6fed04 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87863 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
a9b856e10e
commit
dc87f2ac66
|
@ -53,15 +53,7 @@ namespace dawn::native::metal {
|
|||
using CommandBufferBase::CommandBufferBase;
|
||||
|
||||
MaybeError EncodeComputePass(CommandRecordingContext* commandContext);
|
||||
MaybeError EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
MaybeError EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height);
|
||||
MaybeError EncodeRenderPass(id<MTLRenderCommandEncoder> encoder);
|
||||
};
|
||||
|
||||
} // namespace dawn::native::metal
|
||||
|
|
|
@ -38,15 +38,6 @@ namespace dawn::native::metal {
|
|||
|
||||
namespace {
|
||||
|
||||
// Allows this file to use MTLStoreActionStoreAndMultismapleResolve because the logic is
|
||||
// first to compute what the "best" Metal render pass descriptor is, then fix it up if we
|
||||
// are not on macOS 10.12 (i.e. the EmulateStoreAndMSAAResolve toggle is on).
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
constexpr MTLStoreAction kMTLStoreActionStoreAndMultisampleResolve =
|
||||
MTLStoreActionStoreAndMultisampleResolve;
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
MTLIndexType MTLIndexFormat(wgpu::IndexFormat format) {
|
||||
switch (format) {
|
||||
case wgpu::IndexFormat::Uint16:
|
||||
|
@ -213,83 +204,6 @@ namespace dawn::native::metal {
|
|||
return descriptorRef;
|
||||
}
|
||||
|
||||
// Helper function for Toggle EmulateStoreAndMSAAResolve
|
||||
void ResolveInAnotherRenderPass(
|
||||
CommandRecordingContext* commandContext,
|
||||
const MTLRenderPassDescriptor* mtlRenderPass,
|
||||
const std::array<id<MTLTexture>, kMaxColorAttachments>& resolveTextures) {
|
||||
// Note that this creates a descriptor that's autoreleased so we don't use AcquireNSRef
|
||||
NSRef<MTLRenderPassDescriptor> mtlRenderPassForResolveRef =
|
||||
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassDescriptor* mtlRenderPassForResolve = mtlRenderPassForResolveRef.Get();
|
||||
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (resolveTextures[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mtlRenderPassForResolve.colorAttachments[i].texture =
|
||||
mtlRenderPass.colorAttachments[i].texture;
|
||||
mtlRenderPassForResolve.colorAttachments[i].loadAction = MTLLoadActionLoad;
|
||||
mtlRenderPassForResolve.colorAttachments[i].storeAction =
|
||||
MTLStoreActionMultisampleResolve;
|
||||
mtlRenderPassForResolve.colorAttachments[i].resolveTexture = resolveTextures[i];
|
||||
mtlRenderPassForResolve.colorAttachments[i].resolveLevel =
|
||||
mtlRenderPass.colorAttachments[i].resolveLevel;
|
||||
mtlRenderPassForResolve.colorAttachments[i].resolveSlice =
|
||||
mtlRenderPass.colorAttachments[i].resolveSlice;
|
||||
}
|
||||
|
||||
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)];
|
||||
}
|
||||
|
||||
// Metal uses a physical addressing mode which means buffers in the shading language are
|
||||
// just pointers to the virtual address of their start. This means there is no way to know
|
||||
// the length of a buffer to compute the length() of unsized arrays at the end of storage
|
||||
|
@ -731,8 +645,11 @@ namespace dawn::native::metal {
|
|||
|
||||
LazyClearRenderPassAttachments(cmd);
|
||||
NSRef<MTLRenderPassDescriptor> descriptor = CreateMTLRenderPassDescriptor(cmd);
|
||||
DAWN_TRY(EncodeRenderPass(commandContext, descriptor.Get(), cmd->width,
|
||||
cmd->height));
|
||||
DAWN_TRY(EncodeMetalRenderPass(
|
||||
ToBackend(GetDevice()), commandContext, descriptor.Get(), cmd->width,
|
||||
cmd->height, [this](id<MTLRenderCommandEncoder> encoder) -> MaybeError {
|
||||
return this->EncodeRenderPass(encoder);
|
||||
}));
|
||||
|
||||
nextRenderPassNumber++;
|
||||
break;
|
||||
|
@ -1192,102 +1109,7 @@ namespace dawn::native::metal {
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
MaybeError CommandBuffer::EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
ASSERT(mtlRenderPass);
|
||||
|
||||
Device* device = ToBackend(GetDevice());
|
||||
|
||||
// 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 = {};
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (mtlRenderPass.colorAttachments[i].resolveTexture == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mtlRenderPass.colorAttachments[i].resolveLevel == 0 &&
|
||||
mtlRenderPass.colorAttachments[i].resolveSlice == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (trueResolveTextures[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(temporaryResolveTextures[i] != nullptr);
|
||||
CopyIntoTrueResolveTarget(commandContext, trueResolveTextures[i],
|
||||
trueResolveLevels[i], trueResolveSlices[i],
|
||||
temporaryResolveTextures[i].Get(), width, height);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Store + MSAA resolve workaround (Toggle EmulateStoreAndMSAAResolve).
|
||||
if (device->IsToggleEnabled(Toggle::EmulateStoreAndMSAAResolve)) {
|
||||
bool hasStoreAndMSAAResolve = false;
|
||||
|
||||
// Remove any store + MSAA resolve and remember them.
|
||||
std::array<id<MTLTexture>, kMaxColorAttachments> resolveTextures = {};
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (mtlRenderPass.colorAttachments[i].storeAction ==
|
||||
kMTLStoreActionStoreAndMultisampleResolve) {
|
||||
hasStoreAndMSAAResolve = true;
|
||||
resolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;
|
||||
|
||||
mtlRenderPass.colorAttachments[i].storeAction = MTLStoreActionStore;
|
||||
mtlRenderPass.colorAttachments[i].resolveTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a store + MSAA resolve we need to resolve in a different render pass.
|
||||
if (hasStoreAndMSAAResolve) {
|
||||
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||
ResolveInAnotherRenderPass(commandContext, mtlRenderPass, resolveTextures);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_TRY(EncodeRenderPassInternal(commandContext, mtlRenderPass, width, height));
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError CommandBuffer::EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
MaybeError CommandBuffer::EncodeRenderPass(id<MTLRenderCommandEncoder> encoder) {
|
||||
bool enableVertexPulling = GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling);
|
||||
RenderPipeline* lastPipeline = nullptr;
|
||||
id<MTLBuffer> indexBuffer = nullptr;
|
||||
|
@ -1299,8 +1121,6 @@ namespace dawn::native::metal {
|
|||
VertexBufferTracker vertexBuffers(&storageBufferLengths);
|
||||
BindGroupTracker bindGroups(&storageBufferLengths);
|
||||
|
||||
id<MTLRenderCommandEncoder> encoder = commandContext->BeginRender(mtlRenderPass);
|
||||
|
||||
auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
|
||||
switch (type) {
|
||||
case Command::Draw: {
|
||||
|
@ -1489,7 +1309,6 @@ namespace dawn::native::metal {
|
|||
switch (type) {
|
||||
case Command::EndRenderPass: {
|
||||
mCommands.NextCommand<EndRenderPassCmd>();
|
||||
commandContext->EndRender();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,27 @@ namespace dawn::native::metal {
|
|||
uint32_t sampleMask = 0xFFFFFFFF,
|
||||
const RenderPipeline* renderPipeline = nullptr);
|
||||
|
||||
// Allow use MTLStoreActionStoreAndMultismapleResolve because the logic in the backend is
|
||||
// first to compute what the "best" Metal render pass descriptor is, then fix it up if we
|
||||
// are not on macOS 10.12 (i.e. the EmulateStoreAndMSAAResolve toggle is on).
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
constexpr MTLStoreAction kMTLStoreActionStoreAndMultisampleResolve =
|
||||
MTLStoreActionStoreAndMultisampleResolve;
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
// Helper functions to encode Metal render passes that take care of multiple workarounds that
|
||||
// happen at the render pass start and end. Because workarounds wrap the encoding of the render
|
||||
// pass, the encoding must be entirely done by the `encodeInside` callback.
|
||||
// At the end of this function, `commandContext` will have no encoder open.
|
||||
using EncodeInsideRenderPass = std::function<MaybeError(id<MTLRenderCommandEncoder>)>;
|
||||
MaybeError EncodeMetalRenderPass(Device* device,
|
||||
CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
EncodeInsideRenderPass encodeInside);
|
||||
|
||||
} // namespace dawn::native::metal
|
||||
|
||||
#endif // SRC_DAWN_NATIVE_METAL_UTILSMETAL_H_
|
||||
|
|
|
@ -21,6 +21,85 @@
|
|||
|
||||
namespace dawn::native::metal {
|
||||
|
||||
namespace {
|
||||
// Helper function for Toggle EmulateStoreAndMSAAResolve
|
||||
void ResolveInAnotherRenderPass(
|
||||
CommandRecordingContext* commandContext,
|
||||
const MTLRenderPassDescriptor* mtlRenderPass,
|
||||
const std::array<id<MTLTexture>, kMaxColorAttachments>& resolveTextures) {
|
||||
// Note that this creates a descriptor that's autoreleased so we don't use AcquireNSRef
|
||||
NSRef<MTLRenderPassDescriptor> mtlRenderPassForResolveRef =
|
||||
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassDescriptor* mtlRenderPassForResolve = mtlRenderPassForResolveRef.Get();
|
||||
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (resolveTextures[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mtlRenderPassForResolve.colorAttachments[i].texture =
|
||||
mtlRenderPass.colorAttachments[i].texture;
|
||||
mtlRenderPassForResolve.colorAttachments[i].loadAction = MTLLoadActionLoad;
|
||||
mtlRenderPassForResolve.colorAttachments[i].storeAction =
|
||||
MTLStoreActionMultisampleResolve;
|
||||
mtlRenderPassForResolve.colorAttachments[i].resolveTexture = resolveTextures[i];
|
||||
mtlRenderPassForResolve.colorAttachments[i].resolveLevel =
|
||||
mtlRenderPass.colorAttachments[i].resolveLevel;
|
||||
mtlRenderPassForResolve.colorAttachments[i].resolveSlice =
|
||||
mtlRenderPass.colorAttachments[i].resolveSlice;
|
||||
}
|
||||
|
||||
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) {
|
||||
switch (compareFunction) {
|
||||
case wgpu::CompareFunction::Never:
|
||||
|
@ -285,4 +364,98 @@ namespace dawn::native::metal {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError EncodeMetalRenderPass(Device* device,
|
||||
CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
EncodeInsideRenderPass encodeInside) {
|
||||
// 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 = {};
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (mtlRenderPass.colorAttachments[i].resolveTexture == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mtlRenderPass.colorAttachments[i].resolveLevel == 0 &&
|
||||
mtlRenderPass.colorAttachments[i].resolveSlice == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
DAWN_TRY(EncodeMetalRenderPass(device, commandContext, mtlRenderPass, width, height,
|
||||
std::move(encodeInside)));
|
||||
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (trueResolveTextures[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(temporaryResolveTextures[i] != nullptr);
|
||||
CopyIntoTrueResolveTarget(commandContext, trueResolveTextures[i],
|
||||
trueResolveLevels[i], trueResolveSlices[i],
|
||||
temporaryResolveTextures[i].Get(), width, height);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Store + MSAA resolve workaround (Toggle EmulateStoreAndMSAAResolve).
|
||||
if (device->IsToggleEnabled(Toggle::EmulateStoreAndMSAAResolve)) {
|
||||
bool hasStoreAndMSAAResolve = false;
|
||||
|
||||
// Remove any store + MSAA resolve and remember them.
|
||||
std::array<id<MTLTexture>, kMaxColorAttachments> resolveTextures = {};
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (mtlRenderPass.colorAttachments[i].storeAction ==
|
||||
kMTLStoreActionStoreAndMultisampleResolve) {
|
||||
hasStoreAndMSAAResolve = true;
|
||||
resolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;
|
||||
|
||||
mtlRenderPass.colorAttachments[i].storeAction = MTLStoreActionStore;
|
||||
mtlRenderPass.colorAttachments[i].resolveTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a store + MSAA resolve we need to resolve in a different render pass.
|
||||
if (hasStoreAndMSAAResolve) {
|
||||
DAWN_TRY(EncodeMetalRenderPass(device, commandContext, mtlRenderPass, width, height,
|
||||
std::move(encodeInside)));
|
||||
|
||||
ResolveInAnotherRenderPass(commandContext, mtlRenderPass, resolveTextures);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_TRY(encodeInside(commandContext->BeginRender(mtlRenderPass)));
|
||||
commandContext->EndRender();
|
||||
return {};
|
||||
}
|
||||
} // namespace dawn::native::metal
|
||||
|
|
Loading…
Reference in New Issue