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>
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 72c6443..4427418 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -53,7 +53,7 @@
CommandRecordingContext* GetPendingCommandContext();
void SubmitPendingCommandBuffer();
- TextureBase* CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
+ Ref<Texture> CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane);
void WaitForCommandsToBeScheduled();
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 30e7f2a..0359698 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -409,7 +409,7 @@
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 @@
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() {
diff --git a/src/dawn_native/metal/MetalBackend.mm b/src/dawn_native/metal/MetalBackend.mm
index 74265a23..b8fffaf 100644
--- a/src/dawn_native/metal/MetalBackend.mm
+++ b/src/dawn_native/metal/MetalBackend.mm
@@ -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 @@
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) {
diff --git a/src/dawn_native/metal/SwapChainMTL.mm b/src/dawn_native/metal/SwapChainMTL.mm
index d49ed70..84eb649 100644
--- a/src/dawn_native/metal/SwapChainMTL.mm
+++ b/src/dawn_native/metal/SwapChainMTL.mm
@@ -53,7 +53,8 @@
}
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 @@
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();
}
diff --git a/src/dawn_native/metal/TextureMTL.h b/src/dawn_native/metal/TextureMTL.h
index c03adbf..07ffe23 100644
--- a/src/dawn_native/metal/TextureMTL.h
+++ b/src/dawn_native/metal/TextureMTL.h
@@ -38,14 +38,14 @@
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 @@
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 @@
id<MTLTexture> GetMTLTexture();
private:
- TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor);
+ using TextureViewBase::TextureViewBase;
+ MaybeError Initialize(const TextureViewDescriptor* descriptor);
NSPRef<id<MTLTexture>> mMtlTextureView;
};
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index 8cc642e..3567738 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -352,49 +352,82 @@
// 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 @@
// 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 @@
textureType:textureViewType
levels:mipLevelRange
slices:arrayLayerRange]);
+ if (mMtlTextureView == nil) {
+ return DAWN_INTERNAL_ERROR("Failed to create MTLTexture view.");
+ }
}
+
+ return {};
}
id<MTLTexture> TextureView::GetMTLTexture() {