我想在draw
的MTKView
方法中获取自最后一帧以来的时间(称为
timestep或
deltatime)。假设每秒 60 帧,我希望看到大约
0.017
的值。如果意外减速导致视图仅以每秒 30 帧的速度呈现,则该值应上升到大约 0.03
。我尝试了几种方法。
1/view.preferredFramesPerSecond
:这种方法是不可取的,因为它假定所有帧都将在首选时间执行。如果有减速,时间步长将不准确。
clock()
函数:我注意到,如果我尝试在
clock()
的 draw
方法中使用 MTKView
,deltatime 会关闭大约 10 倍。
最小可复制示例:
在 Xcode 中创建一个新的 'Metal' 游戏模板。应该渲染旋转的彩色立方体的那个。然后,在每帧更新的
draw
方法中,添加行:
// Objective-C
printf("%f\n", (double)clock()/CLOCKS_PER_SEC);
// Swift
print(Double(clock())/Double(CLOCKS_PER_SEC))
构建并观察打印的数字和控制台。
数字以不规则且缓慢的速度增加(大约每秒 0.1 个),而不是稳定地每秒增加 1 个。
我还尝试将之前的结果存储在一个变量中,然后从当前结果中减去并除以
CLOCKS_PER_SEC
。我看到不正确的 deltatime 值约为 0.001
.
clock()
得到的是 CPU 使用时间而不是实时。 clock()
功能不适用于此。
buffer.gpuEndTime-buffer.gpuStartTime
:这种方法与
clock()
方法有类似的问题,但更糟。当没有几何图形被渲染时,我看到 deltatime 下降到大约 1.0e-5
(100 microseconds)。这是几个数量级。
我也试过
buffer.kernelStartTime
而不是buffer.gpuStartTime
无济于事。
此方法还需要 MacOS 10.15 或更新版本。这是不可取的,因为代码应该尽可能向后兼容。
我找不到关于将
clock()
与 Metal 游戏一起使用的相关结果,或者关于如何在 Metal 或 MTKView
中获得任何时间步长或增量时间的相关结果。
如何在 Metal 中简单地获取帧的增量时间(例如,用于精确的物理模拟)?
来自苹果文档:
您可以使用命令缓冲区的 GPUEndTime 和 GPUStartTime 计算 GPU 运行时间的属性 命令缓冲区:
__block dispatch_semaphore_t block_sema = _inFlightSemaphore;
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer)
{
CFTimeInterval start = buffer.GPUStartTime;
CFTimeInterval end = buffer.GPUEndTime;
CFTimeInterval gpuRuntimeDuration = end - start;
printf("%f \n", gpuRuntimeDuration);
dispatch_semaphore_signal(block_sema);
}];
问题:数字以不规则且缓慢的速度增长(大约0.1 每秒)而不是稳定的每秒 1。
正确执行:
clock_t c = clock();
/* .... */
printf("Time: %g sec.\n", (double)(clock() - (c)) / CLOCKS_PER_SEC);
我想获得自上一帧以来的时间(称为时间步长或 deltatime) 在 MTKView 的 draw 方法中。我希望看到的值 大约 0.017 假设每秒 60 帧。这 如果意外减速导致该值应升至 0.03 左右 视图以每秒仅 30 帧的速度呈现。我尝试了几种方法。
在您的类实现中声明两个
CFAbsoluteTime
类型变量:
@implementation Renderer {
/*.....*/
CFAbsoluteTime _deltaTime;
CFAbsoluteTime _currentFrameTime;
}
然后像这样更新您的
MTKView
绘制方法:
- (void)drawInMTKView:(MTKView *)view {
CFAbsoluteTime currentTime = CACurrentMediaTime();
_deltaTime = currentTime - _currentFrameTime;
_currentFrameTime = currentTime;
NSLog(@"%f", _deltaTime);
/*.....*/
}