关于渲染循环策略的思考 [英] Thoughts about rendering loop strategies

查看:113
本文介绍了关于渲染循环策略的思考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这些注意事项的数百种变化已在网上发布.但是,我还没有找到能解决我的确切问题的任何东西,因此希望您能帮助我了解情况.

I know that hundreds of variations of these considerations have been posted all over the net. However, I haven't found anything that adresses my exact problem, so I hope you can help me see the light.

我目前正在使用OpenGL在Java中进行2D游戏开发.使用的语言和图形库与我的问题无关,尽管它具有更通用的特征.

I'm currently toying with 2D game development in Java using OpenGL. The language and graphics library used is not that relevant to my question though as it has a more general character.

我正在尝试设计一个通用游戏循环,该循环可以或多或少地用于具有中等沉重图形(主要是位图纹理)甚至可能是较重游戏逻辑(AI,碰撞检测等)的任何游戏.

I'm attempting to design a general purpose game loop which can be used more or less as is for any game that has moderately heavy graphics (mostly bitmap textures) and possibly even heavier game logic (AI, collision detection, etc).

基本上,我希望维护一个可以被更新(位置,速度和其他与游戏相关的更新)和渲染(位于更新位置的纹理/帧)的对象的列表/数组/缓冲区可能.

Basically I'm expecting to maintain a list/array/buffer of objects that can be updated (positions, velocities, and other game related updates) and rendered (textures/frames at updated positions) non stop as smooth and efficiently as possible.

1)一个线程进行更新和渲染

我尝试并仅使用一个线程(好了,在计算用户输入时是两个)放弃了顺序解决方案.

I have tried and discarded a sequential solution using only one thread (well, two when counting user input).

  • 计算更改并更新缓冲区对象
  • 将纹理的更新位置渲染到后缓冲
  • 将后缓冲交换到前面

显然,在硬件上阻塞交换缓冲区的同时,浪费了大量的计算时间,这需要更有效的解决方案

Apparently a lot of good computing time is wasted while swap-buffers is blocking on the hardware, which calls for a more efficient solution

2)一个线程用于更新,一个线程用于渲染

通过将程序分为更新线程和渲染线程并同步对共享缓冲区的访问,我应该能够确保相当稳定的帧速率.对共享缓冲区的同步访问可以通过多种方式来完成,但是它们都有一个共同点.它们都禁止线程并发.尽管这可能是一个公平的权衡,但我想知道是什么使同步变得必要.

By splitting the program into an update thread and a rendering thread and synchronizing access to the shared buffer I should be able to ensure a pretty steady framerate. Synchronizing access to the shared buffer can be accomplished in many ways, but they all have one thing in common. They all prohibit thread concurrency. While this may be a fair tradeoff, I'm wondering what makes synchronization necessary.

3)与2相同,但没有同步

我确实理解了并发线程的粗心实现可能导致的许多问题.生产者/消费者,读者/作家和类似情况导致潜在的僵局.但是,我不明白,如果满足以下条件(并且应该满足),为什么我需要确保共享数据的同步:

I do understand many of the problems that can be caused by careless implementation of concurrent threads. The producer/consumer, the readers/writers and similar situations causing potential deadlocks. However, I do not understand why I need to ensure synchronization of the shared data if the following criteria are met (and they should be):

  • 渲染线程只能从共享缓冲区读取
  • 更新线程既可以读取共享缓冲区,也可以写入共享缓冲区(因此它是唯一的写程序")
  • 游戏运行时,共享缓冲区永远不会为空或已满
  • 线程永远不会休眠
  • 渲染不必是100%准确的.如果某些共享库尚未更新,导致它们比其他对象落后一个更新步骤(即,大约10-20毫秒),那么任何人都不会注意到.

-

所以...我在这里想念什么明显的东西?为什么需要为此设置进行同步?

So... what obvious thing am I missing here? Why do I need the synchronization for this setup?

  • 如果未正确同步线程,线程是否可以缓存数据而导致问题?
  • 或者如果不幸不幸中断了写线程,数据是否会以某种方式乱码?
  • 或者我提出的策略使它变得无用时是否存在一般性问题?

任何想法,评论或建议都是最欢迎的.或者,如果已经在其他地方解决了这个特定问题,我将为您提供参考.

Any thoughts, comments, or suggestions are most welcome. Or if this particular question has already been addressed elsewhere I would appreciate a reference.

推荐答案

不同步的方法对您来说很好.因此,如果这是库存的Intel硬件 1 则加倍.我仍然不会使用它.

The unsynchronized approach will work just fine for you; doubly so if this is stock Intel hardware1. I would still not use it.

不同步的并发几乎永远无法可靠工作的原因是,处理器可以自由地进行何时在主RAM和缓存之间进行存储和加载.这可以破坏几乎所有不同步的协议.但是,正如您所说,如果您的应用程序中的场景从未发生过突然变化,那么没人会注意到.所有数据都将进入RAM,迟早对其他线程可见.

The reason why unsynchronized concurrency almost never works reliably is that processors have free hand in when to do stores and loads between main RAM and cache. This can subvert almost any unsynchronized protocol. However, as you say, no one is likely to notice if the scenes never abruptly change in your application; all the data will go to the RAM and become visible to the other thread sooner or later.

但是,您无法保证这会在何时何地进行,这在理论上使您有可能以奇怪的方式混合两个后续帧(在突然改变场景或其光照之前和之后).

You however have no guarantee when that will be and in which sequence, which leaves you with a theoretical possibility of mixing two subsequent frames (before and after an abrupt change of the scene or its lighting) in odd ways.

取决于您的编程语言及其内存模型(我想C ++早于C ++ 11?),您可能会发现轻量级同步原语,其保证的副作用是适当的内存障碍,其对性能的影响可以忽略不计.这是我建议的起点.极端的性能优化(超出可以证明的安全范围)应该是优化引擎的最后阶段.

Depending on your programming language and its memory model (C++ older than C++11 I suppose?) you are likely to find lightweight synchronization primitives whose guaranteed side effect are appropriate memory barriers, whose impact on performance will be negligible. This is what I would recommend as a starting point. Extreme performance optimizations (beyond what can be proven safe) should be the last stage of optimizing your engine.

1 ),i86从不对商店进行重新排序.我不认为这在任何地方都有记载,我也不想依赖它.您仍然可以对读取进行重新排序,因此这对您的情况无济于事.

1) i86 never reorders stores. I don't think this is documented anywhere and I would not like relying on it. You can still have reordered reads, so it is no help in your scenario anyway.

这篇关于关于渲染循环策略的思考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆