根据我的经验,在渲染 api 时没有测试代码的最佳实践,因为这里有很多不同的因素:
GPU 和 CPU 供应商(Apple、AMD、Intel)、操作系统、司机。
我同意 Jeshua:
测试硬件兼容性的最佳实践是在实际
您正在测试兼容性的硬件。
有许多有用的方法可以使开发和测试更容易:
您可以检测vendors id:
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
NSString* appleGPU = [device.name containsString:@"Apple"];
NSString* intelGPU = [device.name containsString:@"Intel"];
NSString* amdGPU = [device.name containsString:@"AMD"];
NSString* nvidiaGPU = [device.name containsString:@"Nvidia"];
使用following method,您可以找到您的gpu 类型:
bool externalGPU = [device isRemovable] == true;
bool integratedGPU = [device isLowPower] == true;
bool discreteGPU = [device isLowPower] == false;
注意:
[device isLowPower];
在配备 Apple 硅 M1 芯片的 Mac 上,该属性为 NO,因为
GPU 以高性能和低功耗运行。
确定TBDR GPU 架构:
if (@available(macOS 10.15, *)) {
if ([device supportsFamily: MTLGPUFamilyApple4])
{
// The GPU does support Tile-Based Deferred Rendering technique
}
}
Understand the Managed Mode:
在统一内存模型中,具有 MTLStorageModeManaged 的资源
模式驻留在 CPU 和 GPU 均可访问的系统内存中。
行为类似于MTLStorageModeShared,只有一份内容副本。
注意:
在统一的内存模型中,Metal 可能会忽略
同步调用完全因为它只创建一个
资源的内存分配。
您还可以检查其他开发人员的一些实现:
PixarAnimationStudios/USD:
HgiMetalCapabilities::HgiMetalCapabilities(id<MTLDevice> device)
{
if (@available(macOS 10.14.5, ios 12.0, *)) {
_SetFlag(HgiDeviceCapabilitiesBitsConcurrentDispatch, true);
}
defaultStorageMode = MTLResourceStorageModeShared;
bool unifiedMemory = false;
if (@available(macOS 100.100, ios 12.0, *)) {
unifiedMemory = true;
} else if (@available(macOS 10.15, ios 13.0, *)) {
#if defined(ARCH_OS_IOS) || (defined(__MAC_10_15) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15)
unifiedMemory = [device hasUnifiedMemory];
#else
unifiedMemory = [device isLowPower];
#endif
}
_SetFlag(HgiDeviceCapabilitiesBitsUnifiedMemory, unifiedMemory);
#if defined(ARCH_OS_MACOS)
if (!unifiedMemory) {
defaultStorageMode = MTLResourceStorageModeManaged;
}
#endif
}
KhronosGroup/MoltenVK
// Metal Managed:
// - applies to both buffers and textures
// - default mode for textures on macOS
// - two copies of each buffer or texture when discrete memory available
// - convenience of shared mode, performance of private mode
// - on unified systems behaves like shared memory and has only one copy of content
// - when writing, use:
// - buffer didModifyRange:
// - texture replaceRegion:
// - when reading, use:
// - encoder synchronizeResource: followed by
// - cmdbuff waitUntilCompleted (or completion handler)
// - buffer/texture getBytes: