diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h index f09976a94f..347328a19b 100644 --- a/src/gpu/mtl/GrMtlCaps.h +++ b/src/gpu/mtl/GrMtlCaps.h @@ -96,6 +96,7 @@ public: #if GR_TEST_UTILS std::vector getTestingCombinations() const override; #endif + void onDumpJSON(SkJSONWriter*) const override; private: void initFeatureSet(MTLFeatureSet featureSet); diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm index 59edf6a3c3..99a3ff2256 100644 --- a/src/gpu/mtl/GrMtlCaps.mm +++ b/src/gpu/mtl/GrMtlCaps.mm @@ -1104,3 +1104,43 @@ std::vector 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 diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index 3e30f471d3..5f4e92e580 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -224,6 +224,10 @@ private: void testingOnly_endCapture() override; #endif +#ifdef SK_ENABLE_DUMP_GPU + void onDumpJSON(SkJSONWriter*) const override; +#endif + sk_sp fMtlCaps; id fDevice; diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm index 29453a2015..cedd00db6f 100644 --- a/src/gpu/mtl/GrMtlGpu.mm +++ b/src/gpu/mtl/GrMtlGpu.mm @@ -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 diff --git a/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp b/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp index c289e39b77..e5ff2fa448 100644 --- a/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp +++ b/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp @@ -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; diff --git a/tools/gpu/mtl/MtlTestContext.mm b/tools/gpu/mtl/MtlTestContext.mm index b20a1f8dee..9a654cfe06 100644 --- a/tools/gpu/mtl/MtlTestContext.mm +++ b/tools/gpu/mtl/MtlTestContext.mm @@ -27,7 +27,25 @@ public: device = sharedContextImpl->device(); queue = sharedContextImpl->queue(); } else { +#ifdef SK_BUILD_FOR_MAC + NSArray>* availableDevices = MTLCopyAllDevices(); + // Choose the non-integrated CPU if available + for (id 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]; }