Reland "Set up eGPU/discrete support for MacOS."

This is a reland of 1c3bea4593

Original change's description:
> Set up eGPU/discrete support for MacOS.
> 
> Pulled out of https://skia-review.googlesource.com/c/skia/+/271319.
> 
> For Metal, will default to an eGPU or discrete GPU if one is available.
> For GL, will attempt to use a Radeon eGPU, and will fallback
> if one can't be found.
> 
> Change-Id: I0a1efb3afca612ac75be56f633d811dda68f9d10
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/277516
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Jim Van Verth <jvanverth@google.com>

Change-Id: I1f9dcbf82465533ae8bce96b5cc73a7c627071a4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/277696
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2020-03-18 13:36:32 -04:00 committed by Skia Commit-Bot
parent 8370fd1267
commit d29d885c88
6 changed files with 223 additions and 3 deletions

View File

@ -96,6 +96,7 @@ public:
#if GR_TEST_UTILS
std::vector<TestFormatColorTypeCombination> getTestingCombinations() const override;
#endif
void onDumpJSON(SkJSONWriter*) const override;
private:
void initFeatureSet(MTLFeatureSet featureSet);

View File

@ -1104,3 +1104,43 @@ std::vector<GrCaps::TestFormatColorTypeCombination> GrMtlCaps::getTestingCombina
return combos;
}
#endif
#ifdef SK_ENABLE_DUMP_GPU
#include "src/utils/SkJSONWriter.h"
void GrMtlCaps::onDumpJSON(SkJSONWriter* writer) const {
// We are called by the base class, which has already called beginObject(). We choose to nest
// all of our caps information in a named sub-object.
writer->beginObject("Metal caps");
writer->beginObject("Preferred Stencil Format");
writer->appendS32("stencil bits", fPreferredStencilFormat.fStencilBits);
writer->appendS32("total bits", fPreferredStencilFormat.fTotalBits);
writer->endObject();
switch (fPlatform) {
case Platform::kMac:
writer->appendString("Platform", "Mac");
break;
case Platform::kIOS:
writer->appendString("Platform", "iOS");
break;
default:
writer->appendString("Platform", "unknown");
break;
}
writer->appendS32("Family Group", fFamilyGroup);
writer->appendS32("Version", fVersion);
writer->beginArray("Sample Counts");
for (int v : fSampleCounts) {
writer->appendS32(nullptr, v);
}
writer->endArray();
writer->endObject();
}
#else
void GrMtlCaps::onDumpJSON(SkJSONWriter* writer) const { }
#endif

View File

@ -224,6 +224,10 @@ private:
void testingOnly_endCapture() override;
#endif
#ifdef SK_ENABLE_DUMP_GPU
void onDumpJSON(SkJSONWriter*) const override;
#endif
sk_sp<GrMtlCaps> fMtlCaps;
id<MTLDevice> fDevice;

View File

@ -1421,3 +1421,137 @@ void GrMtlGpu::testingOnly_endCapture() {
}
}
#endif
#ifdef SK_ENABLE_DUMP_GPU
#include "src/utils/SkJSONWriter.h"
void GrMtlGpu::onDumpJSON(SkJSONWriter* writer) const {
// We are called by the base class, which has already called beginObject(). We choose to nest
// all of our caps information in a named sub-object.
writer->beginObject("Metal GPU");
writer->beginObject("Device");
writer->appendString("name", fDevice.name.UTF8String);
#ifdef SK_BUILD_FOR_MAC
if (@available(macOS 10.11, *)) {
writer->appendBool("isHeadless", fDevice.isHeadless);
writer->appendBool("isLowPower", fDevice.isLowPower);
}
if (@available(macOS 10.13, *)) {
writer->appendBool("isRemovable", fDevice.isRemovable);
}
#endif
if (@available(macOS 10.13, iOS 11.0, *)) {
writer->appendU64("registryID", fDevice.registryID);
}
#ifdef SK_BUILD_FOR_MAC
if (@available(macOS 10.15, *)) {
switch (fDevice.location) {
case MTLDeviceLocationBuiltIn:
writer->appendString("location", "builtIn");
break;
case MTLDeviceLocationSlot:
writer->appendString("location", "slot");
break;
case MTLDeviceLocationExternal:
writer->appendString("location", "external");
break;
case MTLDeviceLocationUnspecified:
writer->appendString("location", "unspecified");
break;
default:
writer->appendString("location", "unknown");
break;
}
writer->appendU64("locationNumber", fDevice.locationNumber);
writer->appendU64("maxTransferRate", fDevice.maxTransferRate);
}
#endif // SK_BUILD_FOR_MAC
if (@available(macOS 10.15, iOS 13.0, *)) {
writer->appendBool("hasUnifiedMemory", fDevice.hasUnifiedMemory);
}
#ifdef SK_BUILD_FOR_MAC
if (@available(macOS 10.15, *)) {
writer->appendU64("peerGroupID", fDevice.peerGroupID);
writer->appendU32("peerCount", fDevice.peerCount);
writer->appendU32("peerIndex", fDevice.peerIndex);
}
if (@available(macOS 10.12, *)) {
writer->appendU64("recommendedMaxWorkingSetSize", fDevice.recommendedMaxWorkingSetSize);
}
#endif // SK_BUILD_FOR_MAC
if (@available(macOS 10.13, iOS 11.0, *)) {
writer->appendU64("currentAllocatedSize", fDevice.currentAllocatedSize);
writer->appendU64("maxThreadgroupMemoryLength", fDevice.maxThreadgroupMemoryLength);
}
writer->beginObject("maxThreadsPerThreadgroup");
writer->appendU64("width", fDevice.maxThreadsPerThreadgroup.width);
writer->appendU64("height", fDevice.maxThreadsPerThreadgroup.height);
writer->appendU64("depth", fDevice.maxThreadsPerThreadgroup.depth);
writer->endObject();
if (@available(macOS 10.13, iOS 11.0, *)) {
writer->appendBool("areProgrammableSamplePositionsSupported",
fDevice.areProgrammableSamplePositionsSupported);
writer->appendBool("areRasterOrderGroupsSupported",
fDevice.areRasterOrderGroupsSupported);
}
#ifdef SK_BUILD_FOR_MAC
if (@available(macOS 10.11, *)) {
writer->appendBool("isDepth24Stencil8PixelFormatSupported",
fDevice.isDepth24Stencil8PixelFormatSupported);
}
if (@available(macOS 10.15, *)) {
writer->appendBool("areBarycentricCoordsSupported",
fDevice.areBarycentricCoordsSupported);
writer->appendBool("supportsShaderBarycentricCoordinates",
fDevice.supportsShaderBarycentricCoordinates);
}
#endif // SK_BUILD_FOR_MAC
if (@available(macOS 10.14, iOS 12.0, *)) {
writer->appendU64("maxBufferLength", fDevice.maxBufferLength);
}
if (@available(macOS 10.13, iOS 11.0, *)) {
switch (fDevice.readWriteTextureSupport) {
case MTLReadWriteTextureTier1:
writer->appendString("readWriteTextureSupport", "tier1");
break;
case MTLReadWriteTextureTier2:
writer->appendString("readWriteTextureSupport", "tier2");
break;
case MTLReadWriteTextureTierNone:
writer->appendString("readWriteTextureSupport", "tierNone");
break;
default:
writer->appendString("readWriteTextureSupport", "unknown");
break;
}
switch (fDevice.argumentBuffersSupport) {
case MTLArgumentBuffersTier1:
writer->appendString("argumentBuffersSupport", "tier1");
break;
case MTLArgumentBuffersTier2:
writer->appendString("argumentBuffersSupport", "tier2");
break;
default:
writer->appendString("argumentBuffersSupport", "unknown");
break;
}
}
if (@available(macOS 10.14, iOS 12.0, *)) {
writer->appendU64("maxArgumentBufferSamplerCount", fDevice.maxArgumentBufferSamplerCount);
}
#ifdef SK_BUILD_FOR_IOS
if (@available(iOS 13.0, *)) {
writer->appendU64("sparseTileSizeInBytes", fDevice.sparseTileSizeInBytes);
}
#endif
writer->endObject();
writer->appendString("queue", fQueue.label.UTF8String);
writer->appendBool("disconnected", fDisconnected);
writer->endObject();
}
#endif

View File

@ -40,18 +40,41 @@ private:
MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext)
: fContext(nullptr)
, fGLLibrary(RTLD_DEFAULT) {
// We first try to request a Radeon eGPU if one is available.
// This will be a Radeon HD7000 and up, which includes all eGPU configs.
// If that fails, we try again with only the base parameters.
CGLPixelFormatAttribute attributes[] = {
// base parameters
#if MAC_OS_X_VERSION_10_7
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
kCGLPFAOpenGLProfile,
(CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
#endif
kCGLPFADoubleBuffer,
(CGLPixelFormatAttribute)0
#if MAC_OS_X_VERSION_10_8
// eGPU parameters
kCGLPFAAllowOfflineRenderers, // Enables e-GPU.
kCGLPFANoRecovery, // Disallows software rendering.
kCGLPFARendererID, (CGLPixelFormatAttribute)kCGLRendererATIRadeonX4000ID, // Select Radeon
#endif
(CGLPixelFormatAttribute)NULL
};
#if MAC_OS_X_VERSION_10_8
static const int kFirstEGPUParameter = 3;
SkASSERT(kCGLPFAAllowOfflineRenderers == attributes[kFirstEGPUParameter]);
#endif
CGLPixelFormatObj pixFormat;
GLint npix;
CGLChoosePixelFormat(attributes, &pixFormat, &npix);
#if MAC_OS_X_VERSION_10_8
if (nullptr == pixFormat) {
// Move the NULL-termination up to remove the eGPU parameters and try again
attributes[kFirstEGPUParameter] = (CGLPixelFormatAttribute)NULL;
CGLChoosePixelFormat(attributes, &pixFormat, &npix);
}
#endif
if (nullptr == pixFormat) {
SkDebugf("CGLChoosePixelFormat failed.");
return;

View File

@ -27,7 +27,25 @@ public:
device = sharedContextImpl->device();
queue = sharedContextImpl->queue();
} else {
#ifdef SK_BUILD_FOR_MAC
NSArray<id <MTLDevice>>* availableDevices = MTLCopyAllDevices();
// Choose the non-integrated CPU if available
for (id<MTLDevice> dev in availableDevices) {
if (!dev.isLowPower) {
device = dev;
break;
}
if (dev.isRemovable) {
device = dev;
break;
}
}
if (!device) {
device = MTLCreateSystemDefaultDevice();
}
#else
device = MTLCreateSystemDefaultDevice();
#endif
queue = [device newCommandQueue];
}