Add additional guards in counter set feature checks
- Don't use for..in since some crashes show that NSFastEnumeration in those loops is doing something wrong. - Check that the receiver actually supports the selector before calling it. Crashes indicate an unrecognized selector is being used. - Add a ref to MTLCounterSet to be sure it is not somehow freed between when it is stored, and when we use it as the receiver for [MTLCounterSet counters]. Bug: dawn:1102 Change-Id: I882045ba09547df62a98a862e6e64c5a7d656e80 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/80461 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
cfbd1baf2e
commit
7a8006033a
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "dawn/common/CoreFoundationRef.h"
|
#include "dawn/common/CoreFoundationRef.h"
|
||||||
#include "dawn/common/GPUInfo.h"
|
#include "dawn/common/GPUInfo.h"
|
||||||
|
#include "dawn/common/Log.h"
|
||||||
#include "dawn/common/NSRef.h"
|
#include "dawn/common/NSRef.h"
|
||||||
#include "dawn/common/Platform.h"
|
#include "dawn/common/Platform.h"
|
||||||
#include "dawn/common/SystemUtils.h"
|
#include "dawn/common/SystemUtils.h"
|
||||||
|
@ -187,20 +188,29 @@ namespace dawn::native::metal {
|
||||||
isDrawBoundarySupported;
|
isDrawBoundarySupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method has seen hard-to-debug crashes. See crbug.com/dawn/1102.
|
||||||
|
// For now, it is written defensively, with many potentially unnecessary guards until
|
||||||
|
// we narrow down the cause of the problem.
|
||||||
DAWN_NOINLINE bool IsGPUCounterSupported(id<MTLDevice> device,
|
DAWN_NOINLINE bool IsGPUCounterSupported(id<MTLDevice> device,
|
||||||
MTLCommonCounterSet counterSetName,
|
MTLCommonCounterSet counterSetName,
|
||||||
std::vector<MTLCommonCounter> counterNames)
|
std::vector<MTLCommonCounter> counterNames)
|
||||||
API_AVAILABLE(macos(10.15), ios(14.0)) {
|
API_AVAILABLE(macos(10.15), ios(14.0)) {
|
||||||
// MTLDevice’s counterSets property declares which counter sets it supports. Check
|
NSPRef<id<MTLCounterSet>> counterSet = nil;
|
||||||
// whether it's available on the device before requesting a counter set.
|
if (![device respondsToSelector:@selector(counterSets)]) {
|
||||||
|
dawn::ErrorLog() << "MTLDevice does not respond to selector: counterSets.";
|
||||||
// On some systems, [device counterSets] is null and not an empty array.
|
|
||||||
if ([device counterSets] == nil) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
NSArray<id<MTLCounterSet>>* counterSets = device.counterSets;
|
||||||
id<MTLCounterSet> counterSet = nil;
|
if (counterSets == nil) {
|
||||||
for (id<MTLCounterSet> set in [device counterSets]) {
|
// On some systems, [device counterSets] may be null and not an empty array.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// MTLDevice’s counterSets property declares which counter sets it supports. Check
|
||||||
|
// whether it's available on the device before requesting a counter set.
|
||||||
|
// Note: Don't do for..in loop to avoid potentially crashy interaction with
|
||||||
|
// NSFastEnumeration.
|
||||||
|
for (NSUInteger i = 0; i < counterSets.count; ++i) {
|
||||||
|
id<MTLCounterSet> set = [counterSets objectAtIndex:i];
|
||||||
if ([set.name caseInsensitiveCompare:counterSetName] == NSOrderedSame) {
|
if ([set.name caseInsensitiveCompare:counterSetName] == NSOrderedSame) {
|
||||||
counterSet = set;
|
counterSet = set;
|
||||||
break;
|
break;
|
||||||
|
@ -212,12 +222,25 @@ namespace dawn::native::metal {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (![*counterSet respondsToSelector:@selector(counters)]) {
|
||||||
|
dawn::ErrorLog() << "MTLCounterSet does not respond to selector: counters.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NSArray<id<MTLCounter>>* countersInSet = (*counterSet).counters;
|
||||||
|
if (countersInSet == nil) {
|
||||||
|
// On some systems, [MTLCounterSet counters] may be null and not an empty array.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// A GPU might support a counter set, but only support a subset of the counters in that
|
// A GPU might support a counter set, but only support a subset of the counters in that
|
||||||
// set, check if the counter set supports all specific counters we need. Return false
|
// set, check if the counter set supports all specific counters we need. Return false
|
||||||
// if there is a counter unsupported.
|
// if there is a counter unsupported.
|
||||||
for (MTLCommonCounter counterName : counterNames) {
|
for (MTLCommonCounter counterName : counterNames) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (id<MTLCounter> counter in [counterSet counters]) {
|
// Note: Don't do for..in loop to avoid potentially crashy interaction with
|
||||||
|
// NSFastEnumeration.
|
||||||
|
for (NSUInteger i = 0; i < countersInSet.count; ++i) {
|
||||||
|
id<MTLCounter> counter = [countersInSet objectAtIndex:i];
|
||||||
if ([counter.name caseInsensitiveCompare:counterName] == NSOrderedSame) {
|
if ([counter.name caseInsensitiveCompare:counterName] == NSOrderedSame) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue