64#pragma clang diagnostic push
65#pragma clang diagnostic ignored "-Wdeprecated-declarations"
69 CGLRendererInfoObj ri;
70 GLint rendererCount = 0;
71 CGLQueryRendererInfo(-1, &ri, &rendererCount);
72 for (
int i = 0; i < rendererCount; ++i)
75 CGLDescribeRenderer(ri, i, kCGLRPRendererID, &rendererID);
79 if (CGLDescribeRenderer(ri, i, kCGLRPOnline, &online) == kCGLNoError)
80 VUserLog(
" Online : %s", online ?
"yes" :
"no");
83 if (CGLDescribeRenderer(ri, i, kCGLRPAccelerated, &accelerated) == kCGLNoError)
84 VUserLog(
" Accelerated : %s", accelerated ?
"yes" :
"no");
86 GLint videoMegabytes = 0;
87 if (CGLDescribeRenderer(ri, i, kCGLRPVideoMemoryMegabytes, &videoMegabytes) == kCGLNoError
89 VUserLog(
" Video memory : %d MB", videoMegabytes);
91 GLint textureMegabytes = 0;
92 if (CGLDescribeRenderer(ri, i, kCGLRPTextureMemoryMegabytes, &textureMegabytes) == kCGLNoError
94 VUserLog(
" Texture memory : %d MB", textureMegabytes);
97 if (CGLDescribeRenderer(ri, i, kCGLRPDisplayMask, &displayMask) == kCGLNoError)
99 VUserLog(
" Display mask : %s (0x%x)%s",
100 std::bitset<32>(displayMask).to_string().c_str(),
101 displayMask, (displayMask & 0xff) == 0xff ?
" (any)" :
"");
102 if ((displayMask & 0xff) != 0xff)
103 for (
unsigned long i = 0; i < screenCount; ++i)
104 if (displayMask & screens[i].displayMask)
106 std::bitset<32>(screens[i].displayMask).to_string().c_str(),
111 if (CGLDescribeRenderer(ri, i, (CGLRendererProperty)133, &glVersion) == kCGLNoError)
112 VUserLog(
" OpenGL version : %d", glVersion);
115 if (pf != (CGLPixelFormatObj)-1)
117 CGLContextObj cgl_ctx;
118 CGLError error = CGLCreateContext(pf, NULL, &cgl_ctx);
119 if (error != kCGLNoError)
120 VUserLog(
" Error: %s", CGLErrorString(error));
123 GLint maxTextureSize;
124 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
125 VUserLog(
" OpenGL 2 : %s (%s) maxTextureSize=%d", glGetString(GL_RENDERER), glGetString(GL_VERSION), maxTextureSize);
126 CGLDestroyContext(cgl_ctx);
130 VUserLog(
" (Can't create an OpenGL 2 context on this renderer.)");
133 if (pf != (CGLPixelFormatObj)-1)
135 CGLContextObj cgl_ctx;
136 CGLError error = CGLCreateContext(pf, NULL, &cgl_ctx);
137 if (error != kCGLNoError)
138 VUserLog(
" Error: %s", CGLErrorString(error));
141 GLint maxTextureSize;
142 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
143 VUserLog(
" OpenGL Core Profile: %s (%s) maxTextureSize=%d", glGetString(GL_RENDERER), glGetString(GL_VERSION), maxTextureSize);
144 CGLDestroyContext(cgl_ctx);
148 VUserLog(
" (Can't create an OpenGL Core Profile context on this renderer.)");
150 CGLDestroyRendererInfo(ri);
151#pragma clang diagnostic pop
154 typedef void *(*mtlCopyAllDevicesType)(void);
155 mtlCopyAllDevicesType mtlCopyAllDevices = (mtlCopyAllDevicesType)dlsym(RTLD_DEFAULT,
"MTLCopyAllDevices");
156 if (mtlCopyAllDevices)
158 CFArrayRef mtlDevices = (CFArrayRef)mtlCopyAllDevices();
159 int mtlDeviceCount = CFArrayGetCount(mtlDevices);
162 for (
int i = 0; i < mtlDeviceCount; ++i)
164 id dev = (id)CFArrayGetValueAtIndex(mtlDevices, i);
165 id devName = ((id (*)(id, SEL))objc_msgSend)(dev, sel_getUid(
"name"));
166 const char *devNameZ = ((
char * (*)(
id,
SEL))objc_msgSend)(devName, sel_getUid(
"UTF8String"));
167 VUserLog(
" %s (%s):", devNameZ, class_getName(object_getClass(dev)));
168 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"registryID")))
169 VUserLog(
" ID : %p", ((
id (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"registryID")));
170 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"location")))
172 unsigned long location = ((
unsigned long (*)(id, SEL))objc_msgSend)(dev, sel_getUid(
"location"));
174 location == 0 ?
"built-in" : (location == 1 ?
"slot" : (location == 2 ?
"external" :
"unspecified")),
175 ((
unsigned long (*)(id, SEL))objc_msgSend)(dev, sel_getUid(
"locationNumber")));
177 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"peerGroupID")))
178 VUserLog(
" Peer group : %llu (ID %u of %u)",
179 ((uint64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"peerGroupID")),
180 ((uint32_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"peerIndex")),
181 ((uint32_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"peerCount")));
183 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"recommendedMaxWorkingSetSize")))
184 VUserLog(
" Recommended max working-set size : %lld MiB", ((int64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"recommendedMaxWorkingSetSize"))/1048576);
185 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"maxBufferLength")))
186 VUserLog(
" Max buffer length : %lld MiB", ((int64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"maxBufferLength"))/1048576);
187 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"maxThreadgroupMemoryLength")))
188 VUserLog(
" Threadgroup memory : %lld B", ((int64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"maxThreadgroupMemoryLength")));
189 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"sparseTileSizeInBytes")))
190 VUserLog(
" Sparse tile size : %llu B", ((uint64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"sparseTileSizeInBytes")));
192 VUserLog(
" Low-power : %s", ((
bool (*)(
id,
SEL))objc_msgSend) ?
"yes" :
"no");
193 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"isRemovable")))
194 VUserLog(
" Removable : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"isRemovable")) ?
"yes" :
"no");
195 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"hasUnifiedMemory")))
196 VUserLog(
" Unified memory : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"hasUnifiedMemory")) ?
"yes" :
"no");
197 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"maxTransferRate")))
199 uint64_t maxTransferRate = ((uint64_t (*)(id, SEL))objc_msgSend)(dev, sel_getUid(
"maxTransferRate"));
201 VUserLog(
" Max CPU-GPU RAM transfer rate : %llu MiB/sec", maxTransferRate/1024/1024);
203 VUserLog(
" Headless : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"isHeadless")) ?
"yes" :
"no");
205 if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFeatureSet:"), 10005))
206 VUserLog(
" Feature set : GPU Family 2 v1");
207 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFeatureSet:"), 10004))
208 VUserLog(
" Feature set : GPU Family 1 v4");
209 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFeatureSet:"), 10003))
210 VUserLog(
" Feature set : GPU Family 1 v3");
211 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFeatureSet:"), 10001))
212 VUserLog(
" Feature set : GPU Family 1 v2");
213 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFeatureSet:"), 10000))
214 VUserLog(
" Feature set : GPU Family 1 v1");
216 VUserLog(
" Feature set : (unknown)");
218 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsFamily:")))
222 if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1008))
224 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1007))
226 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1006))
228 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1005))
230 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1004))
232 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1003))
234 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1002))
236 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 1001))
239 if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 2002))
241 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 2001))
244 if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 3003))
246 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 3002))
248 else if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 3001))
251 if (((
bool (*)(
id,
SEL,
int))objc_msgSend)(dev, sel_getUid(
"supportsFamily:"), 5001))
255 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"readWriteTextureSupport")))
256 VUserLog(
" Read-write texture support tier : %lld", ((int64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"readWriteTextureSupport")));
257 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"argumentBuffersSupport")))
258 VUserLog(
" Argument buffer support tier : %lld", ((int64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"argumentBuffersSupport")));
259 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"maxArgumentBufferSamplerCount")))
260 VUserLog(
" Max argument buffers : %lld", ((int64_t (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"maxArgumentBufferSamplerCount")));
261 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"areProgrammableSamplePositionsSupported")))
262 VUserLog(
" Programmable sample position support: %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"areProgrammableSamplePositionsSupported")) ?
"yes" :
"no");
263 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"areRasterOrderGroupsSupported")))
264 VUserLog(
" Raster order group support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"areRasterOrderGroupsSupported")) ?
"yes" :
"no");
266 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsDynamicLibraries")))
267 VUserLog(
" Dynamic library support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsDynamicLibraries")) ?
"yes" :
"no");
268 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsRenderDynamicLibraries")))
269 VUserLog(
" Dynamic render library support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsRenderDynamicLibraries")) ?
"yes" :
"no");
270 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsFunctionPointers")))
271 VUserLog(
" Function pointer support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsFunctionPointers")) ?
"yes" :
"no");
272 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsFunctionPointersFromRender")))
273 VUserLog(
" Render function pointer support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsFunctionPointersFromRender")) ?
"yes" :
"no");
274 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsRaytracing")))
275 VUserLog(
" Raytracing support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsRaytracing")) ?
"yes" :
"no");
276 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsRaytracingFromRender")))
277 VUserLog(
" Render raytracing support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsRaytracingFromRender")) ?
"yes" :
"no");
278 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsShaderBarycentricCoordinates")))
279 VUserLog(
" Barycentric support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsShaderBarycentricCoordinates")) ?
"yes" :
"no");
280 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsPrimitiveMotionBlur")))
281 VUserLog(
" Motion blur support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsPrimitiveMotionBlur")) ?
"yes" :
"no");
282 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsPullModelInterpolation")))
283 VUserLog(
" Multiple interpolation support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsPullModelInterpolation")) ?
"yes" :
"no");
284 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supports32BitFloatFiltering")))
285 VUserLog(
" 32-bit float support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supports32BitFloatFiltering")) ?
"yes" :
"no");
286 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supports32BitMSAA")))
287 VUserLog(
" 32-bit MSAA support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supports32BitMSAA")) ?
"yes" :
"no");
288 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsQueryTextureLOD")))
289 VUserLog(
" LOD query support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsQueryTextureLOD")) ?
"yes" :
"no");
290 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"supportsBCTextureCompression")))
291 VUserLog(
" BC texture support : %s", ((
bool (*)(
id,
SEL))objc_msgSend)(dev, sel_getUid(
"supportsBCTextureCompression")) ?
"yes" :
"no");
293 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"sparseTileSizeInBytesForSparsePageSize:")))
295 VUserLog(
" 16-byte sparse page tile size : %llu", ((uint64_t (*)(
id,
SEL, uint64_t))objc_msgSend)(dev, sel_getUid(
"sparseTileSizeInBytesForSparsePageSize:"), 101));
296 VUserLog(
" 64-byte sparse page tile size : %llu", ((uint64_t (*)(
id,
SEL, uint64_t))objc_msgSend)(dev, sel_getUid(
"sparseTileSizeInBytesForSparsePageSize:"), 102));
297 VUserLog(
" 256-byte sparse page tile size : %llu", ((uint64_t (*)(
id,
SEL, uint64_t))objc_msgSend)(dev, sel_getUid(
"sparseTileSizeInBytesForSparsePageSize:"), 103));
300 if (class_respondsToSelector(object_getClass(dev), sel_getUid(
"counterSets")))
302 id counterSets = ((id (*)(id, SEL))objc_msgSend)(dev, sel_getUid(
"counterSets"));
303 id description = ((id (*)(id, SEL))objc_msgSend)(counterSets, sel_getUid(
"description"));
306 string descriptionS{((
const char * (*)(
id,
SEL))objc_msgSend)(description, sel_getUid(
"UTF8String"))};
307 std::replace(descriptionS.begin(), descriptionS.end(),
'\n',
' ');
308 VUserLog(
" Counters : %s", descriptionS.c_str());
312 CFRelease(mtlDevices);
725#pragma clang diagnostic push
726#pragma clang diagnostic ignored "-Wdeprecated-declarations"
728 static dispatch_once_t multisamplingCheck = 0;
729 static int multisample = 0;
730 dispatch_once(&multisamplingCheck, ^{
732 CGLContextObj cgl_ctx;
734 CGLPixelFormatObj pf;
736 CGLPixelFormatAttribute pfa[14] = {
738 kCGLPFAAllowOfflineRenderers,
741 kCGLPFABackingVolatile,
742 kCGLPFAColorSize, (CGLPixelFormatAttribute) 24,
743 kCGLPFADepthSize, (CGLPixelFormatAttribute) (hasDepthBuffer ? 16 : 0),
744 (CGLPixelFormatAttribute) 0
747 CGLError error = CGLChoosePixelFormat(pfa, &pf, &npix);
748 if (error != kCGLNoError)
750 VUserLog(
"Error: %s", CGLErrorString(error));
755 CGLError error = CGLCreateContext(pf, NULL, &cgl_ctx);
756 CGLDestroyPixelFormat(pf);
757 if (error != kCGLNoError)
759 VUserLog(
"Error: %s", CGLErrorString(error));
766 Boolean overridden =
false;
767 multisample = (int)CFPreferencesGetAppIntegerValue(CFSTR(
"multisample"), CFSTR(
"org.vuo.Editor"), &overridden);
774 multisample =
MIN(4, supportedSamples);
777 CGLDestroyContext(cgl_ctx);
781 CGLPixelFormatAttribute pfa[18];
785 if (displayMask == -1)
786 pfa[pfaIndex++] = kCGLPFAAccelerated;
788 pfa[pfaIndex++] = kCGLPFAAllowOfflineRenderers;
793 pfa[pfaIndex++] = kCGLPFABackingVolatile;
795 pfa[pfaIndex++] = kCGLPFAColorSize; pfa[pfaIndex++] = (CGLPixelFormatAttribute) 24;
796 pfa[pfaIndex++] = kCGLPFADepthSize; pfa[pfaIndex++] = (CGLPixelFormatAttribute) (hasDepthBuffer ? 16 : 0);
799 pfa[pfaIndex++] = kCGLPFAOpenGLProfile; pfa[pfaIndex++] = (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core;
804 pfa[pfaIndex++] = kCGLPFAMultisample;
805 pfa[pfaIndex++] = kCGLPFASampleBuffers; pfa[pfaIndex++] = (CGLPixelFormatAttribute) 1;
806 pfa[pfaIndex++] = kCGLPFASamples; pfa[pfaIndex++] = (CGLPixelFormatAttribute) multisample;
809 if (displayMask >= 0)
811 pfa[pfaIndex++] = kCGLPFADisplayMask;
812 pfa[pfaIndex++] = (CGLPixelFormatAttribute) displayMask;
816 if ((displayMask & 0xff) == 0xff && displayMask != -1)
818 pfa[pfaIndex++] = kCGLPFARendererID;
819 pfa[pfaIndex++] = (CGLPixelFormatAttribute) kCGLRendererGenericFloatID;
822 pfa[pfaIndex] = (CGLPixelFormatAttribute) 0;
824 CGLPixelFormatObj pf;
826 CGLError error = CGLChoosePixelFormat(pfa, &pf, &npix);
827 if (error == kCGLBadDisplay)
828 return (CGLPixelFormatObj)-1;
829 else if (error != kCGLNoError)
831 VUserLog(
"Error: %s", CGLErrorString(error));
836#pragma clang diagnostic pop