gpt4 book ai didi

ios - 为什么 renderInContext 比绘制到屏幕慢得多?

转载 作者:行者123 更新时间:2023-12-01 19:55:05 31 4
gpt4 key购买 nike

我有一个相当大的CAShapeLayer我正在渲染。该层是完全静态的,但它包含在 UIScrollView 中所以它可以移动和缩放——基本上,它必须时不时地重新绘制。为了提高滚动的帧率,我设置了 shouldRasterize = YES在图层上,效果非常好。因为我从不更改图层的任何属性,所以它永远不会出现光栅化缺失,并且我得到了稳定的 60 fps。大家击掌,对吧?

直到图层变大一点。最终,不久之后,光栅化图像变得太大,GPU 无法处理。根据我的控制台,<Notice>: CoreAnimation: surface 2560 x 4288 is too large ,它只是不在屏幕上绘制任何内容。我并不真的责怪它- 2560 x 4288相当大——但我花了一段时间才在设备控制台中注意到这一点。

现在,我的问题是:如何解决此限制?如何栅格化一个非常大的图层?

显而易见的解决方案似乎是将图层分解为多个子图层,例如每个象限一个子图层,然后独立地对每个子图层进行栅格化。是否有捷径可寻?我可以创建一个新图层来渲染另一图层的矩形区域吗?或者我应该探索其他一些解决方案?

编辑

创建平铺复合 Material 似乎性能非常差,因为每次进入屏幕时都会重新光栅化图层,从而产生非常不稳定的滚动体验。有什么方法可以缓存这些光栅化吗?或者这是完全错误的方法?

编辑

好吧,这是我当前的解决方案:将图层渲染一次到 CGImageRef 。使用该图像中的子矩形创建多个图 block 图层,并将它们实际放置在屏幕上。

- (CALayer *)getTiledLayerFromLayer:(CALayer *)sourceLayer withHorizontalTiles:(int)horizontalTiles verticalTiles:(int)verticalTiles
{
CALayer *containerLayer = [CALayer layer];
CGFloat tileWidth = sourceLayer.bounds.size.width / horizontalTiles;
CGFloat tileHeight = sourceLayer.bounds.size.height / verticalTiles;

// make sure these are integral, otherwise you'll have image alignment issues!
NSLog(@"tileWidth:%f height:%f", tileWidth, tileHeight);

UIGraphicsBeginImageContextWithOptions(sourceLayer.bounds.size, NO, 0);
CGContextRef tileContext = UIGraphicsGetCurrentContext();
[sourceLayer renderInContext:tileContext];
CGImageRef image = CGBitmapContextCreateImage(tileContext);
UIGraphicsEndImageContext();

for(int horizontalIndex = 0; horizontalIndex < horizontalTiles; horizontalIndex++) {
for(int verticalIndex = 0; verticalIndex < verticalTiles; verticalIndex++) {
CGRect frame = CGRectMake(horizontalIndex * tileWidth, verticalIndex * tileHeight, tileWidth, tileHeight);
CGRect visibleRect = CGRectMake(horizontalIndex / (CGFloat)horizontalTiles, verticalIndex / (CGFloat)verticalTiles, 1.0f / horizontalTiles, 1.0f / verticalTiles);
CALayer *tile = [CALayer layer];
tile.frame = frame;
tile.contents = (__bridge id)image;
tile.contentsRect = visibleRect;
[containerLayer addSublayer:tile];
}
}

CGImageRelease(image);

return containerLayer;
}

这很有效......有点。一方面,我得到了 1980 x 3330 的 60fps 平移和缩放。视网膜 iPad 上的图层。另一方面,启动需要20秒!因此,虽然这个解决方案解决了我原来的问题,但它给了我一个新问题:如何更快地生成图 block ?

从字面上看,所有时间都花在 [sourceLayer renderInContext:tileContext]; 上。称呼。这对我来说似乎很奇怪,因为根据 Core Animation Instrument 的说法,如果我直接添加该层,我每秒可以渲染大约 40 次。创建我自己的图像上下文是否有可能导致它不使用 GPU 或其他东西?

最佳答案

将图层分成图 block 是唯一的解决方案。然而,您可以通过许多不同的方式来实现它。我建议手动执行此操作(自行创建图层和子图层),但许多人建议使用 CATiledLayer http://www.mlsite.net/blog/?p=1857 ,这是 map 通常实现的方式 - 使用这种方式缩放和旋转非常容易。 CATiledLayer 的图 block 在它们被放置到屏幕上之后按需加载(绘制)。这意味着在完全绘制图 block 之前会有短暂的延迟(闪烁),并且据我所知,很难摆脱这种行为。

关于ios - 为什么 renderInContext 比绘制到屏幕慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10094009/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com