Metal: Handle failures in Texture and TextureView creation.

This includes OOM as well as internal driver failures when
creating a view of an MTLTexture. This required changing the code to use
the Create-Initialize pattern used everywhere else.

Bug: dawn:801

Change-Id: Ib8a8dec74141aacfa58a55bb8201a83351b3b739
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/58721
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Corentin Wallez 2021-07-21 09:34:28 +00:00 committed by Dawn LUCI CQ
parent 28497129d5
commit 03f9437ae8
6 changed files with 101 additions and 47 deletions

View File

@ -53,7 +53,7 @@ namespace dawn_native { namespace metal {
CommandRecordingContext* GetPendingCommandContext();
void SubmitPendingCommandBuffer();
TextureBase* CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
Ref<Texture> CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane);
void WaitForCommandsToBeScheduled();

View File

@ -409,7 +409,7 @@ namespace dawn_native { namespace metal {
return {};
}
TextureBase* Device::CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
Ref<Texture> Device::CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane) {
const TextureDescriptor* textureDescriptor =
@ -423,7 +423,12 @@ namespace dawn_native { namespace metal {
return nullptr;
}
return new Texture(this, descriptor, ioSurface, plane);
Ref<Texture> result;
if (ConsumedError(Texture::CreateFromIOSurface(this, descriptor, ioSurface, plane),
&result)) {
return nullptr;
}
return result;
}
void Device::WaitForCommandsToBeScheduled() {

View File

@ -17,8 +17,8 @@
#include "dawn_native/MetalBackend.h"
#include "dawn_native/Texture.h"
#include "dawn_native/metal/DeviceMTL.h"
#include "dawn_native/metal/TextureMTL.h"
namespace dawn_native { namespace metal {
@ -34,9 +34,9 @@ namespace dawn_native { namespace metal {
WGPUTexture WrapIOSurface(WGPUDevice cDevice,
const ExternalImageDescriptorIOSurface* cDescriptor) {
Device* device = reinterpret_cast<Device*>(cDevice);
TextureBase* texture = device->CreateTextureWrappingIOSurface(
Ref<TextureBase> texture = device->CreateTextureWrappingIOSurface(
cDescriptor, cDescriptor->ioSurface, cDescriptor->plane);
return reinterpret_cast<WGPUTexture>(texture);
return reinterpret_cast<WGPUTexture>(texture.Detach());
}
void WaitForCommandsToBeScheduled(WGPUDevice cDevice) {

View File

@ -53,7 +53,8 @@ namespace dawn_native { namespace metal {
}
id<MTLTexture> nativeTexture = reinterpret_cast<id<MTLTexture>>(next.texture.ptr);
return new Texture(ToBackend(GetDevice()), descriptor, nativeTexture);
return Texture::CreateWrapping(ToBackend(GetDevice()), descriptor, nativeTexture).Detach();
}
MaybeError OldSwapChain::OnBeforePresent(TextureViewBase*) {
@ -131,9 +132,8 @@ namespace dawn_native { namespace metal {
TextureDescriptor textureDesc = GetSwapChainBaseTextureDescriptor(this);
// TODO(dawn:723): change to not use AcquireRef for reentrant object creation.
mTexture = AcquireRef(
new Texture(ToBackend(GetDevice()), &textureDesc, [*mCurrentDrawable texture]));
mTexture = Texture::CreateWrapping(ToBackend(GetDevice()), &textureDesc,
[*mCurrentDrawable texture]);
// TODO(dawn:723): change to not use AcquireRef for reentrant object creation.
return mTexture->APICreateView();
}

View File

@ -38,14 +38,14 @@ namespace dawn_native { namespace metal {
public:
static ResultOrError<Ref<Texture>> Create(Device* device,
const TextureDescriptor* descriptor);
Texture(Device* device,
const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> mtlTexture);
Texture(Device* device,
const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane);
static ResultOrError<Ref<Texture>> CreateFromIOSurface(
Device* device,
const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane);
static Ref<Texture> CreateWrapping(Device* device,
const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> wrapped);
id<MTLTexture> GetMTLTexture();
@ -53,9 +53,17 @@ namespace dawn_native { namespace metal {
const SubresourceRange& range);
private:
Texture(Device* device, const TextureDescriptor* descriptor);
using TextureBase::TextureBase;
~Texture() override;
MaybeError InitializeAsInternalTexture(const TextureDescriptor* descriptor);
MaybeError InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
const TextureDescriptor* textureDescriptor,
IOSurfaceRef ioSurface,
uint32_t plane);
void InitializeAsWrapping(const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> wrapped);
void DestroyImpl() override;
MaybeError ClearTexture(CommandRecordingContext* commandContext,
@ -74,7 +82,8 @@ namespace dawn_native { namespace metal {
id<MTLTexture> GetMTLTexture();
private:
TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor);
using TextureViewBase::TextureViewBase;
MaybeError Initialize(const TextureViewDescriptor* descriptor);
NSPRef<id<MTLTexture>> mMtlTextureView;
};

View File

@ -352,49 +352,82 @@ namespace dawn_native { namespace metal {
// static
ResultOrError<Ref<Texture>> Texture::Create(Device* device,
const TextureDescriptor* descriptor) {
return AcquireRef(new Texture(device, descriptor));
Ref<Texture> texture =
AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
DAWN_TRY(texture->InitializeAsInternalTexture(descriptor));
return texture;
}
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
// static
ResultOrError<Ref<Texture>> Texture::CreateFromIOSurface(
Device* device,
const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane) {
const TextureDescriptor* textureDescriptor =
reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
Ref<Texture> texture =
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedInternal));
DAWN_TRY(texture->InitializeFromIOSurface(descriptor, textureDescriptor, ioSurface, plane));
return texture;
}
// static
Ref<Texture> Texture::CreateWrapping(Device* device,
const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> wrapped) {
Ref<Texture> texture =
AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
texture->InitializeAsWrapping(descriptor, std::move(wrapped));
return texture;
}
MaybeError Texture::InitializeAsInternalTexture(const TextureDescriptor* descriptor) {
Device* device = ToBackend(GetDevice());
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
mMtlUsage = [*mtlDesc usage];
mMtlTexture =
AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()]);
mMtlUsage = [*mtlDesc usage];
if (mMtlTexture == nil) {
return DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate texture.");
}
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
device->ConsumedError(ClearTexture(device->GetPendingCommandContext(),
GetAllSubresources(),
TextureBase::ClearValue::NonZero));
DAWN_TRY(ClearTexture(device->GetPendingCommandContext(), GetAllSubresources(),
TextureBase::ClearValue::NonZero));
}
return {};
}
Texture::Texture(Device* device,
const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> mtlTexture)
: TextureBase(device, descriptor, TextureState::OwnedInternal),
mMtlTexture(std::move(mtlTexture)) {
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
void Texture::InitializeAsWrapping(const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> wrapped) {
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(GetDevice(), descriptor);
mMtlUsage = [*mtlDesc usage];
mMtlTexture = std::move(wrapped);
}
Texture::Texture(Device* device,
const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane)
: TextureBase(device,
reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor),
TextureState::OwnedInternal) {
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(
device, reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor));
MaybeError Texture::InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
const TextureDescriptor* textureDescriptor,
IOSurfaceRef ioSurface,
uint32_t plane) {
Device* device = ToBackend(GetDevice());
NSRef<MTLTextureDescriptor> mtlDesc =
CreateMetalTextureDescriptor(device, textureDescriptor);
[*mtlDesc setStorageMode:kIOSurfaceStorageMode];
mMtlUsage = [*mtlDesc usage];
mMtlTexture = AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
iosurface:ioSurface
plane:plane]);
mMtlUsage = [*mtlDesc usage];
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
return {};
}
Texture::~Texture() {
@ -625,12 +658,14 @@ namespace dawn_native { namespace metal {
// static
ResultOrError<Ref<TextureView>> TextureView::Create(TextureBase* texture,
const TextureViewDescriptor* descriptor) {
return AcquireRef(new TextureView(texture, descriptor));
Ref<TextureView> view = AcquireRef(new TextureView(texture, descriptor));
DAWN_TRY(view->Initialize(descriptor));
return view;
}
TextureView::TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor)
: TextureViewBase(texture, descriptor) {
id<MTLTexture> mtlTexture = ToBackend(texture)->GetMTLTexture();
MaybeError TextureView::Initialize(const TextureViewDescriptor* descriptor) {
Texture* texture = ToBackend(GetTexture());
id<MTLTexture> mtlTexture = texture->GetMTLTexture();
if (!UsageNeedsTextureView(texture->GetUsage())) {
mMtlTextureView = nullptr;
@ -663,7 +698,12 @@ namespace dawn_native { namespace metal {
textureType:textureViewType
levels:mipLevelRange
slices:arrayLayerRange]);
if (mMtlTextureView == nil) {
return DAWN_INTERNAL_ERROR("Failed to create MTLTexture view.");
}
}
return {};
}
id<MTLTexture> TextureView::GetMTLTexture() {