2012-05-17 10 views
1

OpenGL ES에서 실행 루프를 만들었습니다.이 루프는 60fps로 CADisplayLink에서 호출합니다. AFAIK CADisplayLink는 그것을 배경 스레드라고합니다.보안 상태 변경을 수행하는 게임 엔진의 전략은 무엇입니까?

실행 루프에서 사용하는 약 100 개의 상태 변수가 있습니다.

문제 : 메인 스레드에서 실행 루프에 사용 된 상태 변수를 변경하여 무언가를 그려야합니다. 프레임은 모든 상태 변수가 목표 값으로 설정된 후에 만 ​​그려야합니다.

상태 변수를 변경할 때 어떤 점에서 두려워요. 그리고 기하학적 모양의 위치와 같이 (주 스레드에서 동일한 반복 루프 반복에서 하나의 큰 방법으로) 모두 변경하지 않았습니다. , 멀티 스레딩과 관련된 충돌이나 문제가 있습니다. CADisplayLink가 메소드 중간에서 상태 변수를 업데이트하고 쓰레기 나 충돌을 일으키는 경우가 있습니다.

분명히 동기화 된 속성이나 원자 속성을 사용할 때 트랜잭션이 아니기 때문에 도움이되지 않습니다. 나는 거래가 필요할 것 같아.

내 순진하게 접근 방식은 이것이다 : 실행 루프에 의해 읽기

인스턴스 변수 : updatingState가 YES 읽는 경우

BOOL updatingState; 

런 루프 방법은 그림을 건너 뜁니다.

그런 다음 상태를 변경하기 전에 나는 YES로 설정합니다. 모든 것이 바뀌면 다시 NO로 설정합니다.

물론 문제는 : 실행 루프 방법이 값을 읽는 중입니까?

어떻게 게임 엔진이이 문제를 해결합니까? 어떤 종류의 잠금 메커니즘을 가지고있어서 다음 프레임이 그려지기 전에 상태 변수의 변경이 완료 될 수 있습니까?

답변

2

읽기 - 복사 - 업데이트 전략이 유용 할 수 있습니다. 한 가지 가능한 구현은 각 객체가 실제로 렌더링 매개 변수의 두 사본을 포함하고 원자 플래그를 사용하여 렌더링 스레드에 사용할 것을 알리는 것입니다. 렌더러에서 읽기 메모리 장벽을 사용하여 매개 변수 중 하나를 읽고 플래그를 뒤집기 전에 모든 매개 변수 업데이트가 기록되었는지 확인하기 위해 업데이터 스레드에서 쓰기 메모리 장벽을 읽기 전에 플래그를 읽어야합니다 .

+0

더 나은 전략은 최상위 수준 포인터 또는 개체 참조 또는 배열 인덱스와 두 개의 완전한 상태 트리를 갖는 것입니다. 최상위 레벨 포인터는 원자 적 명령어를 사용하여 읽고 쓰여야합니다. 읽기 전용 트리는 새 상태를 만드는 데 사용되며 렌더링 엔진은 읽기 전용 트리에서도 읽습니다. 새 상태가 준비되면 최상위 수준 포인터/인덱스/참조가 업데이트됩니다. –

1

일반적인 방법은 모든 상태 업데이트가 드로잉이 완료되기 전에 각 실행 루프 반복에서 발생한다는 것입니다. 즉, 실행 루프는 다음과 같이 구성됩니다.

updateState(); 
draw(); 

이 모델에서는 일관된 상태에 도달 한 후에 만 ​​드로잉이 발생합니다.

이 기능을 사용하려면 비동기로 발생하는 대신 각 updateState()에서 키 누름과 같은 이벤트를 폴링하는 모델이 필요하며 각 반복마다 시간 경과 측정 도구가 필요합니다. 마지막 프레임.

iOS 프로그래밍의 구체적인 경우에는 이것이 어떻게 실현되는지는 잘 모르겠지만 나는 그것에 대해 아무 것도 모른다. 그러나 나는 당신을 올바른 방향으로 가리킬 수 있기를 바랍니다.

1

나는이 동시성의 공통 문제라고 생각합니다, 그래서 그것을 할 수있는 몇 가지 방법이 있습니다 :

  1. 이 상태 변수를 개최 불변 상태 클래스를 사용하여이.
  2. 상태 변수를 보호하기 위해 잠금 메커니즘 (변경 불가능한 클래스를 사용할 수없는 경우)을 사용하십시오.
  3. 수정할 수있는 상태가 여러 개 있지만 하나만 활성화되어 있습니다."이것은 당신이 상태를 재사용 할 수 있으며 복사 및 메모리 할당을 줄일 수

을 또한 생각이 상황 :..

스레드 1. 그리기 뭔가
스레드 1 읽기 1/2 상태 01 매개 변수 (첫 번째 상태)
스레드 2. 상태 02 (두 번째 상태)로 상태 01을 스왑합니다.
스레드 1. 상태 02의 다른 1/2을 읽지 만 상태 01 매개 변수와 다릅니다.

그래서 가장 좋은 방법은 아닙니다. 그리기 도중 상태를 업데이트 할 수 있으므로 옵션 3은 가장 최근의 상태를 가져 와서 그리기 때문에 가장 좋은 방법 일 수 있습니다. 두 상태 : drawingStatenonDrawingState이 있다고 가정 해 보겠습니다. 드로잉 기능에서는 항상 drawingState을 사용하여 다른 스레드가 nonDrawingState을 수정하는 동안 그립니다. 그리기가 끝나면 상태를 교환하고 최신 상태 수정을 사용하여 그리기를 계속할 수 있습니다.

관련 문제