2016-08-01 6 views
4

최근 fogleman의 우수한 "Minecraft in 500 lines"데모를 https://github.com/fogleman/Craft에서 다운로드했습니다. 필자는 2to3 도구를 사용하여 손으로 일부 세부 사항을 수정하여 python3에서 실행되도록했습니다. 나는 이제 render 메서드에서 self.clear()이라는 호출을 가진 것에 대해 궁금해합니다. 당신이 볼 수 있듯이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에 의해 매 프레임마다 호출 방법이다. .../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() 중 하나를 측정했습니다. 렌더링 자체가 10 밀리 초보다 오래 걸리지 않는다는 것을 알게되었습니다. 그러나 glClear()의 기간은 다른 이야기의 비트가 여기에 서로 다른 조건에서 3 개 측정 분포입니다 :
Duration of glClear() under different conditions.

마젠타 라인은 프레임의 시간 제한을 보여줍니다. 그래서 첫 줄 뒤에있는 모든 것은 프레임이 떨어지는 것을 의미합니다.
glClear()의 실행 시간은 첫 번째 프레임이 만료 된 후 일종의 "echo"처럼 보입니다. 왜 나 한테 설명 할 수 있니? 그리고 어떻게 전화를 더 빨리 할 수 ​​있습니까?
불행히도 저는 OpenGL 전문가가 아니므로 모든 조언자에게 감사드립니다. ;)

+1

타이머 해상도는 단순히 "에코"를 설명하는 16ms 일 수 있습니다. https://docs.python.org/2/library/time.html#time.time에서 "모든 시스템이 1 초보다 우수한 정밀도로 시간을 제공하지는 않습니다."를 참조하십시오. 다른 타이머를 사용해보고 중요한지 확인하십시오. – TWT

답변

0

그래프가 잘못되었습니다. 음, 성능 측정 목적에 적합한 그래프가 아닙니다. gl* 함수를 말하면 실행할 함수를 신뢰하지 말고 기대 한만큼 빨리 실행하도록 신뢰하지 마십시오.

대부분의 gl* 기능이 즉시 실행되지는 않습니다. 우리가 GPU를 다루고 있다는 것을 기억하십시오. 직접적으로 일을한다고 말하는 것은 느립니다. 그래서 우리는 GPU를위한 to-do list (command queue)를 작성하고, 이 실제로 일 때 뭔가를 출력하기 위해 VRAM에 덤프합니다. 이 "덤프"는 동기화라는 프로세스의 일부이며 glFlush으로 트리거 할 수 있습니다. OpenGL은 사용자 친화적이지만 (적어도 Vulkan과 비교하면), 명령 대기열을 명시 적으로 플러시하는 데 의존하지 않습니다. 그래픽 드라이버에 따라 달라지는 많은 gl* 함수는 암시 적으로 플러시가 포함 된 CPU와 GPU 상태를 동기화합니다.

보통 glClear이 프레임을 시작하므로 드라이버가 암시 적 동기화를 수행하는 것이 좋을 것이라고 생각할 수 있습니다. 상상할 수 있듯이 동기화는 매우 느린 프로세스이며 완료 될 때까지 CPU 실행을 차단합니다.

그리고 아마도 여기에서 진행될 것입니다. 동기화 프로세스의 일부는 메모리 트랜잭션 (예 : glBufferData, glTexImage*)을 수행하는 것입니다.이 트랜잭션은 glClear 호출로 플러시 될 때까지 대기합니다. 당신의 모범에 맞는 말이 있습니다. 우리가 볼 수있는 스파이크는 블록 데이터를 많이 업로드 한 후 프레임 일 것입니다.

하지만이 점은 순수한 추측 일 뿐이며, 나는 이런 종류의 물건에 대해 완전한 전문가가 아니기 때문에 정확한 세부 사항을 신뢰하지 마십시오.OpenGL wiki의 This page은 이런 종류의 좋은 리소스입니다.

한 가지 확실한 점은, glClear 호출이 프로파일 작성자가 말하는 한 오래 걸리지 않는다는 것입니다. 그래픽 프로파일 링 전용 프로파일 러를 사용해야합니다.

관련 문제