如何在 MTKView 中计算帧时间步长/增量时间?

问题描述 投票:0回答:2

我想在drawMTKView方法中获取自最后一帧以来的时间(称为

timestep
deltatime
)。假设每秒 60 帧,我希望看到大约
0.017
的值。如果意外减速导致视图仅以每秒 30 帧的速度呈现,则该值应上升到大约
0.03
。我尝试了几种方法。

1/view.preferredFramesPerSecond

这种方法是不可取的,因为它假定所有帧都将在首选时间执行。如果有减速,时间步长将不准确。

C
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 中简单地获取帧的增量时间(例如,用于精确的物理模拟)?

time metal timedelta timestep mtkview
2个回答
1
投票

来自苹果文档

您可以使用命令缓冲区的 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);

0
投票

我想获得自上一帧以来的时间(称为时间步长或 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);

    /*.....*/
}
© www.soinside.com 2019 - 2024. All rights reserved.