그래픽 리소스를 비동기식으로로드하는 방법


9

플랫폼에 구애받지 않는다고 생각합시다. 게임의 나머지 부분이 실행되는 동안 그래픽 리소스를로드하고 싶습니다.

원칙적으로 실제 파일을 별도의 스레드 또는 비동기 I / O를 사용하여로드 할 수 있습니다. 그러나 그래픽 객체를 사용하면 GPU에 업로드해야하며 주 스레드에서만 수행 할 수 있습니다.

게임 루프를 다음과 같이 바꿀 수 있습니다.

while true do
    update()
    for each pending resource do
        load resource to gpu
    end
    draw()
end

디스크에서 RAM으로 별도의 스레드로드 자원이있는 동안.

그러나로드 할 큰 리소스가 많은 경우 프레임 마감 시간이 누락되어 결국 프레임이 삭제 될 수 있습니다. 루프를 다음과 같이 변경할 수 있습니다.

while true do
    update()
    if there are pending resources then
        load one resource to gpu
        remove that resource from the pending list
    end
    draw()
end

프레임 당 하나의 리소스 만 효과적으로로드합니다. 그러나로드 할 작은 자원이 많으면 모두로드하는 데 많은 프레임이 필요하며 많은 시간이 낭비됩니다.

최적의로드 시간은 다음과 같습니다.

while true do
    time_start = get_time()
    update()
    while there are pending resources then
        current_time = get_time()
        if (current_time - time_start) + time_to_load(resource) >= 1/60 then
            break
        load one resource to gpu
        remove that resource from the pending list
    end
    draw()
end

이렇게하면 해당 프레임에 대해 시간 내에 리소스를 사용할 수있는 경우에만 리소스를로드합니다. 불행히도, 이것은 주어진 리소스를로드하는데 걸리는 시간을 추정 할 수있는 방법을 필요로합니다.

내가 여기서 무엇을 놓치고 있습니까? 많은 게임이 프레임을 완전히 떨어 뜨리거나 로딩 시간이 너무 길지 않고 완전히 비동기식으로 모든 내용을로드하는 방법은 무엇입니까?

답변:


7

완벽한 세상을 가정하면서 시작합시다. 리소스를로드하는 두 가지 단계가 있습니다. 먼저 스토리지 미디어에서 올바른 형식으로 메모리로 가져오고 두 번째 단계는 메모리 버스를 통해 비디오 메모리로 전송합니다. 이 두 단계 중 어느 것도 실제로 메인 스레드에서 시간을 사용할 필요가 없습니다. I / O 명령을 실행하기 위해 참여하면됩니다. 리소스가 복사되는 동안 CPU와 GPU 모두 다른 작업을 계속할 수 있습니다. 소비되는 유일한 실제 리소스는 메모리 대역폭입니다.

사용자와 하드웨어 사이에 많은 추상화 계층이없는 플랫폼을 사용하는 경우 API가 이러한 개념을 직접 노출 할 수 있습니다. 그러나 PC를 사용하고 있다면 GPU 드라이버와 사용자 사이에 드라이버가있을 수 있습니다. 이 API에 따라 당신은 할 수 있습니다 드라이버가 소유 한 일부 메모리에 텍스처를 복사합니다 "텍스처를 만들"API를 호출 할 가능성이 소유하는 메모리의 지원되지만 텍스처를 만들 수 있습니다. 이 경우 텍스처를 생성하면 고정 된 오버 헤드와 텍스처의 크기에 비례하는 시간이 있습니다. 그 후 드라이버는 무엇이든 할 수 있습니다. 텍스쳐를 VRAM으로 사전에 전송하거나 처음으로 렌더를 시도 할 때까지 텍스쳐 업로드를 방해하지 않을 수 있습니다.

당신은 그것에 대해 무언가를 할 수도 있고하지 않을 수도 있지만 , "텍스처 생성"호출을하는 데 걸리는 시간을 추측 할 수 있습니다 . 물론 하드웨어와 소프트웨어에 따라 모든 숫자가 변경되므로 리버스 엔지니어링에 많은 시간을 할애 할 가치가 없습니다. 그냥 시도해보십시오! "프레임 당 텍스처 수"또는 "프레임 당 텍스처의 총 크기"와 같은 메트릭을 선택하고 할당량 (예 : 프레임 당 4 개의 텍스처)을 선택한 다음 스트레스 테스트를 시작하십시오.

병리학적인 경우, 두 할당량을 동시에 추적해야 할 수도 있습니다 (예 : 프레임 당 4 개의 텍스처 또는 프레임 당 2MB의 텍스처 중 작은 쪽). 그러나 대부분의 텍스처 스트리밍에 대한 실제 요령은 텍스처를 복사하는 데 걸리는 시간이 아니라 제한된 메모리에 맞추려는 텍스처를 파악하는 것 입니다 .

또한, 한 번에 많은 작은 텍스처가 필요한 것처럼 텍스처 생성을위한 병리학 적 사례는 다른 영역의 병리학 적 사례이기도합니다. 텍스처를 복사하는 데 몇 마이크로 초가 걸리는지 걱정하기 전에 간단한 작업 구현을 얻는 것이 좋습니다. 또한 실제 텍스처 적중은 "텍스처 생성"호출에서 CPU 시간으로 발생하는 대신 텍스처를 사용하는 첫 번째 프레임에서 GPU 시간으로 발생할 수 있습니다.


꽤 좋은 설명입니다. 내가 알지 못했지만 많은 의미가 있습니다. 스트레스 테스트 대신 런타임에 텍스처 생성 오버 헤드를 측정하고 부드럽게 시작하여 스로틀을 실행하여 사용 가능한 실행 시간의 80 %를 초과하여 공간을 확보 할 수 있습니다.
Panda Pajama

@ PandaPajama 나는 약간 회의적입니다. 나는 꾸준한 상태가 "텍스처가 복사되지 않음"이고 엄청난 양의 변화가 예상됩니다. 그리고 내가 말했듯이, 히트의 일부는 텍스처를 사용하는 첫 번째 렌더 프레임이라고 생각합니다.이 프레임은 성능에 영향을 미치지 않고 동적으로 측정하기가 훨씬 어렵습니다.
John Calsbeek

또한 비동기 텍스처 전송에 대한 NVIDIA 프레젠테이션이 있습니다. 내가 읽는 한 집으로 운전하는 핵심은 업로드 후 텍스처를 너무 빨리 사용하면 정지한다는 것입니다. developer.download.nvidia.com/GTC/PDF/GTC2012/PresentationPDF/…
John Calsbeek

나는 드라이버 개발자 기수가 아니지만 그게 일반적인가요? 텍스처 첫 사용은 타임 라인을 따라 간격을 두는 대신 스파이크가 발생할 가능성이 높기 때문에 드라이버를 이런 식으로 구현하는 것은 의미가 없습니다.
Panda Pajama

@PandaPajama 응용 프로그램에서 사용 가능한 VRAM보다 많은 텍스처를 만들고 텍스처를 만든 다음 사용하지 않는 것이 일반적입니다. 일반적인 경우는 "그릴 바로 다음 장면을 텍스처의 무리를 생성하고 사용하는 그들,"이 경우는 알아낼 수 있기 때문에 게으른 텍스처가 실제로 사용되는 드라이버를하는 데 도움이, 그 첫 번째 프레임은 히치 하이킹을 가고있는에 어쨌든 . 그러나 나는 또한 드라이버 개발자가 아니며 소금 한 알로 가져 가십시오 (테스트하십시오!).
John Calsbeek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.