2016-08-01 42 views
4

最近、foglemanの優れた「Minecraft in 500 lines」デモをhttps://github.com/fogleman/Craftからダウンロードしました。私は2to3ツールを使って、python3で実行可能にするためにいくつかの詳細を手作業で修正しました3。私は今レンダリングメソッドでself.clear()という呼び出しを持つことについて疑問を呈しています。これはpygletによってすべてのフレームと呼ばれる私の修正レンダリング手法である:あなたが見ることができるようにPython minecraft pyglet glClear()フレームをスキップする

def on_draw(self): 
    """ Called by pyglet to draw the canvas. 

    """ 
    frameStart = time.time() 
    self.clear() 
    clearTime = time.time() 
    self.set_3d() 
    glColor3d(1, 1, 1) 
    self.model.batch.draw() 
    self.draw_focused_block() 
    self.set_2d() 
    self.draw_label() 
    self.draw_reticle() 
    renderTime = time.time() 

    self.clearBuffer.append(str(clearTime - frameStart)) 
    self.renderBuffer.append(str(renderTime - clearTime)) 

、私はself.clear()とレンダリング方法の残りの実行時間を取りました。 .../pyglet /ウィンドウ/ __ init__.pyで発見することができますself.clear()通話pygletのこのメソッドの呼び出し、:

def clear(self): 
    '''Clear the window. 

    This is a convenience method for clearing the color and depth 
    buffer. The window must be the active context (see `switch_to`). 
    ''' 
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) 

は、だから私は基本的にglClear()への呼び出しを作るのですか。
ゲームをテストしている間に(60FPSで)いくつかのフレームドロップが発生したので、上記のコードを追加してコマンドの実行時間を測定しました。特にglClear()の1つです。私はレンダリング自体が10ミリ秒以上かかることはないことを知りました。しかしglClear()の持続時間は、別の話のビットは、ここで異なる条件下での3回の測定のための分布である:
Duration of glClear() under different conditions.

マゼンタラインはフレームの時間制限を示します。したがって、最初の行の後ろのすべては、フレームドロップがあったことを意味します。
glClear()の実行時間は、最初のフレームの有効期限が切れた後、何らかの "エコー"が発生しているようです。なぜ私に説明できますか?そして、私はどのようにして電話をもっと早くすることができますか
残念ながら私はOpenGLのエキスパートではないので、すべてのアドバイス担当者に感謝しています。 ;)

+1

タイマーの解像度は単純に16ミリ秒で、「エコー」を説明することができます。 https://docs.python.org/2/library/time.html#time.timeを参照してください。「すべてのシステムが1秒以上の精度で時間を提供するわけではありません」別のタイマーを試して、それが重要かどうかを確認してください。 – TWT

答えて

0

グラフが間違っています。少なくともパフォーマンスを測定するのに適したグラフではありません。 gl*関数を実行すると信じてはいけません。あなたがそれを告げるときに実行する関数は、あなたが期待するほど速く実行することを信頼することはありません。

ほとんどのgl*機能はすぐに実行されず、実行できません。覚えておいて、私たちはGPUを扱っています。直接行うことは遅いと言っています。代わりに、我々は本当にが何かを出力するためにGPUを必要とするときに、GPUのためのto-doリスト(コマンドキュー)を書き込み、それをVRAMにダンプします。この「ダンプ」は同期と呼ばれるプロセスの一部であり、glFlushでトリガーすることができます。 OpenGLはユーザーフレンドリーですが(少なくとも、Vulkanと比べて)、コマンドキューを明示的にフラッシュするのに頼るものではありません。多くのgl*関数は、グラフィックスドライバに依存しますが、フラッシュを含むCPUとGPUの状態を暗黙的に同期します。

通常、glClearはフレームを開始するので、暗黙的な同期を実行するとよいとドライバが考えている可能性があります。想像しているように、同期は非常に遅いプロセスであり、完了するまでCPUの実行をブロックします。

これはおそらくここで起こっていることです。同期処理の一部は、メモリトランザクション(glBufferDataglTexImage*など)を実行することです。このトランザクションは、glClearコールでフラッシュされるまでキューに入れられている可能性があります。あなたの例では意味があります。私たちが見ることができるスパイクは、おそらく多くのブロックデータをアップロードした後のフレームです。

しかし、これは単なる純粋な推測であり、私はこの種のものについて総合的な専門家でもないので、正確な詳細について私を信頼しないでください。OpenGL wiki上のThis pageは、この種のものの良いリソースです。

1つのことは確実ですが、glClearコールではプロファイラーの指示通りの時間がかかりません。グラフィックのプロファイリング専用のプロファイラを使用する必要があります。

関連する問題