Metal: Handle potential OOM in other places.

This commit adds checks to (hopefully) all the remaining places in the
Metal backend where object creation can fail.

Bug: dawn:801

Change-Id: Ic27803e956beef822f94ca8449f7816ddd17c1bc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/58722
Commit-Queue: Stephen White <senorblanco@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Corentin Wallez 2021-07-20 21:08:39 +00:00 committed by Dawn LUCI CQ
parent b24e1320fc
commit 02a603b613
7 changed files with 47 additions and 30 deletions

View File

@ -223,10 +223,11 @@ namespace dawn_native { namespace metal {
} }
// Helper functions for Toggle AlwaysResolveIntoZeroLevelAndLayer // Helper functions for Toggle AlwaysResolveIntoZeroLevelAndLayer
NSPRef<id<MTLTexture>> CreateResolveTextureForWorkaround(Device* device, ResultOrError<NSPRef<id<MTLTexture>>> CreateResolveTextureForWorkaround(
MTLPixelFormat mtlFormat, Device* device,
uint32_t width, MTLPixelFormat mtlFormat,
uint32_t height) { uint32_t width,
uint32_t height) {
NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]); NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
MTLTextureDescriptor* mtlDesc = mtlDescRef.Get(); MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
@ -241,7 +242,12 @@ namespace dawn_native { namespace metal {
mtlDesc.storageMode = MTLStorageModePrivate; mtlDesc.storageMode = MTLStorageModePrivate;
mtlDesc.sampleCount = 1; mtlDesc.sampleCount = 1;
return AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc]); 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, void CopyIntoTrueResolveTarget(CommandRecordingContext* commandContext,
@ -1144,8 +1150,8 @@ namespace dawn_native { namespace metal {
trueResolveSlices[i] = mtlRenderPass.colorAttachments[i].resolveSlice; trueResolveSlices[i] = mtlRenderPass.colorAttachments[i].resolveSlice;
const MTLPixelFormat mtlFormat = trueResolveTextures[i].pixelFormat; const MTLPixelFormat mtlFormat = trueResolveTextures[i].pixelFormat;
temporaryResolveTextures[i] = DAWN_TRY_ASSIGN(temporaryResolveTextures[i], CreateResolveTextureForWorkaround(
CreateResolveTextureForWorkaround(device, mtlFormat, width, height); device, mtlFormat, width, height));
mtlRenderPass.colorAttachments[i].resolveTexture = mtlRenderPass.colorAttachments[i].resolveTexture =
temporaryResolveTextures[i].Get(); temporaryResolveTextures[i].Get();

View File

@ -43,9 +43,10 @@ namespace dawn_native { namespace metal {
newComputePipelineStateWithFunction:computeData.function.Get() newComputePipelineStateWithFunction:computeData.function.Get()
error:&error]); error:&error]);
if (error != nullptr) { if (error != nullptr) {
NSLog(@" error => %@", error); return DAWN_INTERNAL_ERROR("Error creating pipeline state" +
return DAWN_INTERNAL_ERROR("Error creating pipeline state"); std::string([error.localizedDescription UTF8String]));
} }
ASSERT(mMtlComputePipelineState != nil);
// Copy over the local workgroup size as it is passed to dispatch explicitly in Metal // Copy over the local workgroup size as it is passed to dispatch explicitly in Metal
Origin3D localSize = GetStage(SingleShaderStage::Compute).metadata->localWorkgroupSize; Origin3D localSize = GetStage(SingleShaderStage::Compute).metadata->localWorkgroupSize;

View File

@ -53,8 +53,8 @@ namespace dawn_native { namespace metal {
[device->GetMTLDevice() newCounterSampleBufferWithDescriptor:descriptor [device->GetMTLDevice() newCounterSampleBufferWithDescriptor:descriptor
error:&error]; error:&error];
if (error != nullptr) { if (error != nullptr) {
const char* errorString = [error.localizedDescription UTF8String]; return DAWN_OUT_OF_MEMORY_ERROR(std::string("Error creating query set: ") +
return DAWN_INTERNAL_ERROR(std::string("Error creating query set: ") + errorString); [error.localizedDescription UTF8String]);
} }
return counterSampleBuffer; return counterSampleBuffer;
@ -80,6 +80,10 @@ namespace dawn_native { namespace metal {
mVisibilityBuffer = AcquireNSPRef([device->GetMTLDevice() mVisibilityBuffer = AcquireNSPRef([device->GetMTLDevice()
newBufferWithLength:bufferSize newBufferWithLength:bufferSize
options:MTLResourceStorageModePrivate]); options:MTLResourceStorageModePrivate]);
if (mVisibilityBuffer == nil) {
return DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate query set.");
}
break; break;
} }
case wgpu::QueryType::PipelineStatistics: case wgpu::QueryType::PipelineStatistics:

View File

@ -406,20 +406,19 @@ namespace dawn_native { namespace metal {
descriptorMTL.sampleCount = GetSampleCount(); descriptorMTL.sampleCount = GetSampleCount();
descriptorMTL.alphaToCoverageEnabled = IsAlphaToCoverageEnabled(); descriptorMTL.alphaToCoverageEnabled = IsAlphaToCoverageEnabled();
{ NSError* error = nullptr;
NSError* error = nullptr; mMtlRenderPipelineState =
mMtlRenderPipelineState = AcquireNSPRef([mtlDevice newRenderPipelineStateWithDescriptor:descriptorMTL
AcquireNSPRef([mtlDevice newRenderPipelineStateWithDescriptor:descriptorMTL error:&error]);
error:&error]); if (error != nullptr) {
if (error != nullptr) { return DAWN_INTERNAL_ERROR(std::string("Error creating pipeline state") +
NSLog(@" error => %@", error); [error.localizedDescription UTF8String]);
return DAWN_INTERNAL_ERROR("Error creating rendering pipeline state");
}
} }
ASSERT(mMtlRenderPipelineState != nil);
// Create depth stencil state and cache it, fetch the cached depth stencil state when we // Create depth stencil state and cache it, fetch the cached depth stencil state when we
// call setDepthStencilState() for a given render pipeline in CommandEncoder, in order to // call setDepthStencilState() for a given render pipeline in CommandEncoder, in order
// improve performance. // to improve performance.
NSRef<MTLDepthStencilDescriptor> depthStencilDesc = NSRef<MTLDepthStencilDescriptor> depthStencilDesc =
MakeDepthStencilDesc(GetDepthStencilState()); MakeDepthStencilDesc(GetDepthStencilState());
mMtlDepthStencilState = mMtlDepthStencilState =

View File

@ -33,7 +33,8 @@ namespace dawn_native { namespace metal {
id<MTLSamplerState> GetMTLSamplerState(); id<MTLSamplerState> GetMTLSamplerState();
private: private:
Sampler(Device* device, const SamplerDescriptor* descriptor); using SamplerBase::SamplerBase;
MaybeError Initialize(const SamplerDescriptor* descriptor);
NSPRef<id<MTLSamplerState>> mMtlSamplerState; NSPRef<id<MTLSamplerState>> mMtlSamplerState;
}; };

View File

@ -58,11 +58,12 @@ namespace dawn_native { namespace metal {
return DAWN_VALIDATION_ERROR("Sampler compare function not supported."); return DAWN_VALIDATION_ERROR("Sampler compare function not supported.");
} }
return AcquireRef(new Sampler(device, descriptor)); Ref<Sampler> sampler = AcquireRef(new Sampler(device, descriptor));
DAWN_TRY(sampler->Initialize(descriptor));
return sampler;
} }
Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor) MaybeError Sampler::Initialize(const SamplerDescriptor* descriptor) {
: SamplerBase(device, descriptor) {
NSRef<MTLSamplerDescriptor> mtlDescRef = AcquireNSRef([MTLSamplerDescriptor new]); NSRef<MTLSamplerDescriptor> mtlDescRef = AcquireNSRef([MTLSamplerDescriptor new]);
MTLSamplerDescriptor* mtlDesc = mtlDescRef.Get(); MTLSamplerDescriptor* mtlDesc = mtlDescRef.Get();
@ -87,8 +88,13 @@ namespace dawn_native { namespace metal {
// Metal debug device errors. // Metal debug device errors.
} }
mMtlSamplerState = mMtlSamplerState = AcquireNSPRef(
AcquireNSPRef([device->GetMTLDevice() newSamplerStateWithDescriptor:mtlDesc]); [ToBackend(GetDevice())->GetMTLDevice() newSamplerStateWithDescriptor:mtlDesc]);
if (mMtlSamplerState == nil) {
return DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate sampler.");
}
return {};
} }
id<MTLSamplerState> Sampler::GetMTLSamplerState() { id<MTLSamplerState> Sampler::GetMTLSamplerState() {

View File

@ -332,11 +332,11 @@ namespace dawn_native { namespace metal {
error:&error]); error:&error]);
if (error != nullptr) { if (error != nullptr) {
if (error.code != MTLLibraryErrorCompileWarning) { if (error.code != MTLLibraryErrorCompileWarning) {
const char* errorString = [error.localizedDescription UTF8String];
return DAWN_VALIDATION_ERROR(std::string("Unable to create library object: ") + return DAWN_VALIDATION_ERROR(std::string("Unable to create library object: ") +
errorString); [error.localizedDescription UTF8String]);
} }
} }
ASSERT(library != nil);
NSRef<NSString> name = NSRef<NSString> name =
AcquireNSRef([[NSString alloc] initWithUTF8String:remappedEntryPointName.c_str()]); AcquireNSRef([[NSString alloc] initWithUTF8String:remappedEntryPointName.c_str()]);