Collect device information on Metal

Becuase CGDisplayIOServicePort is deprecated in OSX >= 10.9, we create
an alternative function which manually finding a service port with
matching vendor and product IDs.

BUG=dawn:10
TEST=dawn_end2end_tests

Change-Id: I94ff65911e159c2b7075209d8902c1551560ed47
Reviewed-on: https://dawn-review.googlesource.com/c/2541
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Li Hao 2018-11-29 10:54:03 +00:00 committed by Commit Bot service account
parent ac71e34d4a
commit 813bfbd061
3 changed files with 97 additions and 3 deletions

View File

@ -478,6 +478,7 @@ source_set("libdawn_native_sources") {
libs += [
"Metal.framework",
"Cocoa.framework",
"IOKit.framework",
]
sources += [
"src/dawn_native/metal/BlendStateMTL.h",

View File

@ -33,10 +33,96 @@
#include "dawn_native/metal/SwapChainMTL.h"
#include "dawn_native/metal/TextureMTL.h"
#include <IOKit/graphics/IOGraphicsLib.h>
#include <unistd.h>
namespace dawn_native { namespace metal {
namespace {
// Since CGDisplayIOServicePort was deprecated in macOS 10.9, we need create
// an alternative function for getting I/O service port from current display.
io_service_t GetDisplayIOServicePort() {
// The matching service port (or 0 if none can be found)
io_service_t servicePort = 0;
// Create matching dictionary for display service
CFMutableDictionaryRef matchingDict = IOServiceMatching("IODisplayConnect");
if (matchingDict == nullptr) {
return 0;
}
io_iterator_t iter;
// IOServiceGetMatchingServices look up the default master ports that match a
// matching dictionary, and will consume the reference on the matching dictionary,
// so we don't need to release the dictionary, but the iterator handle should
// be released when its iteration is finished.
if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter) !=
kIOReturnSuccess) {
return 0;
}
// Vendor number and product number of current main display
const uint32_t displayVendorNumber = CGDisplayVendorNumber(kCGDirectMainDisplay);
const uint32_t displayProductNumber = CGDisplayModelNumber(kCGDirectMainDisplay);
io_service_t serv;
while ((serv = IOIteratorNext(iter)) != IO_OBJECT_NULL) {
CFDictionaryRef displayInfo =
IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName);
CFNumberRef vendorIDRef, productIDRef;
Boolean success;
// The ownership of CF object follows the 'Get Rule', we don't need to
// release these values
success = CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayVendorID),
(const void**)&vendorIDRef);
success &= CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayProductID),
(const void**)&productIDRef);
if (success) {
CFIndex vendorID = 0, productID = 0;
CFNumberGetValue(vendorIDRef, kCFNumberSInt32Type, &vendorID);
CFNumberGetValue(productIDRef, kCFNumberSInt32Type, &productID);
if (vendorID == displayVendorNumber && productID == displayProductNumber) {
// Check if vendor id and product id match with current display's
// If it does, we find the desired service port
servicePort = serv;
CFRelease(displayInfo);
break;
}
}
CFRelease(displayInfo);
IOObjectRelease(serv);
}
IOObjectRelease(iter);
return servicePort;
}
// Get integer property from registry entry.
uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef name) {
uint32_t value = 0;
// Recursively search registry entry and its parents for property name
// The data should release with CFRelease
CFDataRef data = static_cast<CFDataRef>(IORegistryEntrySearchCFProperty(
entry, kIOServicePlane, name, kCFAllocatorDefault,
kIORegistryIterateRecursively | kIORegistryIterateParents));
if (data != nullptr) {
const uint32_t* valuePtr =
reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data));
if (valuePtr) {
value = *valuePtr;
}
CFRelease(data);
}
return value;
}
} // anonymous namespace
dawnDevice CreateDevice(id<MTLDevice> metalDevice) {
return reinterpret_cast<dawnDevice>(new Device(metalDevice));
}
@ -200,8 +286,15 @@ namespace dawn_native { namespace metal {
return mResourceUploader.get();
}
// TODO(jiawei.shao@intel.com): collect device information on Metal
void Device::CollectPCIInfo() {
io_registry_entry_t entry = GetDisplayIOServicePort();
if (entry != IO_OBJECT_NULL) {
mPCIInfo.vendorId = GetEntryProperty(entry, CFSTR("vendor-id"));
mPCIInfo.deviceId = GetEntryProperty(entry, CFSTR("device-id"));
IOObjectRelease(entry);
}
mPCIInfo.name = std::string([mMtlDevice.name UTF8String]);
}
}} // namespace dawn_native::metal

View File

@ -365,7 +365,7 @@ TEST_P(TextureViewTest, Texture2DViewOn2DArrayTexture) {
// Test sampling from a 2D array texture view created on a 2D array texture.
TEST_P(TextureViewTest, Texture2DArrayViewOn2DArrayTexture) {
DAWN_SKIP_TEST_IF(IsMetal());
DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
Texture2DArrayViewTest(6, 1, 2, 0);
}
@ -381,7 +381,7 @@ TEST_P(TextureViewTest, Texture2DViewOnOneLevelOf2DArrayTexture) {
// Test sampling from a 2D array texture view created on a mipmap level of a 2D array texture.
TEST_P(TextureViewTest, Texture2DArrayViewOnOneLevelOf2DArrayTexture) {
DAWN_SKIP_TEST_IF(IsMetal());
DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
Texture2DArrayViewTest(6, 6, 2, 4);
}