代码之家  ›  专栏  ›  技术社区  ›  Mark Ingram

从专用渲染线程/循环渲染到camertallayer

  •  1
  • Mark Ingram  · 技术社区  · 7 年前

    在Windows世界中,专用的渲染线程将循环类似以下内容的内容:

    void RenderThread()
    {
        while (!quit)
        {
            UpdateStates();
            RenderToDirect3D();
            // Can either present with no synchronisation,
            // or synchronise after 1-4 vertical blanks.
            // See docs for IDXGISwapChain::Present
            PresentToSwapChain();
        }
    }
    

    可可和什么相当 CAMetalLayer ?所有示例都处理在主线程中执行的更新,或者使用 MTKView (使用内部计时器)或使用 CADisplayLink 在iOS示例中。

    我希望能够控制整个渲染循环,而不仅仅是在某个非指定的时间间隔内接收回调(如果启用了v-sync,最好是阻止它)。

    2 回复  |  直到 7 年前
        1
  •  4
  •   warrenm    7 年前

    在某种程度上,你会被抽屉的可用性所限制。一 CAMetalLayer 有一个固定的抽屉可用,并呼叫 nextDrawable 将阻塞当前线程,直到可绘制文件可用。这并不意味着你必须打电话 可拉伸的 不过,在渲染循环的顶部。

    如果你想在不被阻止的情况下按照自己的时间表绘制,等待绘制,则渲染到屏幕外的渲染器Buffer(即 MTLTexture 尺寸与您的可绘制尺寸相匹配),然后从最近绘制的纹理到可绘制的纹理,以您喜欢的节奏呈现。这对于获取帧计时很有用,但是您绘制的每一帧然后不显示都是浪费的工作。这也增加了发生犹太教的风险。

    当涉及到与v-sync节奏匹配的回调时,您的选择是有限的。你的最佳状态几乎肯定是 CVDisplayLink 在默认和跟踪运行循环模式下调度,尽管 caveats .

    如果你想在不走得太远的情况下自由运行,你可以使用类似于计数信号和显示链接的方式。

    如果你的应用程序能够保持实时的帧速率,你通常会在玻璃上呈现一到两帧,所以你不想直接阻止v-sync;你只想通知窗口服务器你想显示与v-sync匹配。在MacOS上,通过设置层的 displaySyncEnabled 为真(默认值)。关闭此项可能会导致某些显示器撕裂。

        2
  •  2
  •   Ken Thomases    7 年前

    在要渲染到屏幕的点上,通过调用 nextDrawable . 你可以从它的 texture 财产。使用该纹理设置 MTLRenderPassDescriptor . 例如:

    id<CAMetalDrawable> drawable = layer.nextDrawable;
    id<MTLTexture> texture = drawable.texture;
    MTLRenderPassDescriptor *desc = [MTLRenderPassDescriptor renderPassDescriptor];
    desc.colorAttachments[0].texture = texture;
    

    从这里开始,它和你在 MTKView drawRect: 方法。创建命令缓冲区(如果还没有),使用描述符创建呈现命令编码器,对绘图命令进行编码,结束编码,告诉命令缓冲区显示可绘制文件(使用 -presentDrawable:... 方法),并提交命令缓冲区。无论是什么吸引到了抽屉的纹理是什么最终会出现在屏幕上,当它出现。

    我同意沃伦的观点,你可能不想把你的循环与显示器刷新同步。你想要平行。您希望CPU在GPU渲染最新帧时处理下一帧(显示屏显示最后一帧)。

    一次飞行的抽屉数量是有限制的 可拉伸的 将阻止等待一个将阻止渲染循环前进太远。(在此之前,您可能会使用其他一些同步,例如管理一个小的缓冲池。)如果只需要双缓冲而不需要三缓冲,则可以设置层的 maximumDrawableCount 设置为2而不是默认值3。

    推荐文章