2009년 02월 05일
Nebula3 Resource subsystem
이 포스트는 floh님의블로그에 포스팅된 Nebula3 관련 내용을번역한 글입니다. Nebula3는 Nebula2의 기본적인 아키텍쳐를 계승하지만구현에서는 이전과 비교해 보면 여러 면에서 많이 다릅니다. 특히 세개의 레이어로 구성되어 있는 점이 가장 큰 특징 중의 하나인데이것은 이전의 망갈로(Mangalore)가 게임엔진에 포함되었기 때문입니다. 그래서 이 세 개의 레이어에 대한 이해를 위해서 관련된 포스트들만 먼저 번역해서 올립니다.
Nebula3 Resource subsystem
http://flohofwoe.blogspot.com/2007/05/nebula3-resource-subsystem.html
Nebula3의 Resource 서브시스템은 Nebula2와 비교할 때 더욱 열려 있으며 리소스의 생성과 관리에 대해서는 프로그래머에게 더 많은 권한을 위임하고 있다.
Nebula3의 리소스는 다음과 같은 속성을 가지고 있다.
저수준에서는 실제 리소스 객체와 리소스 공유, 로딩, 그리고 다소 중요도는 떨어지지만 저장과 같은 처리를 제공한다. 저수준의 리소스 클래스는 다음과 같다.
ResourceId는 리소스에 대한 유일한 식별자이다. 리소스 아이디는 공유와 디스크 상에서의 리소스 데이터의 위치나 데이터 저장에 사용된다. ResourceId는 문자열 atom이다. Atom은 문자열 상수(혹은 다른 복잡한 데이터타입)에 대한 유니크한 32비트 식별자로 잦은 복사나 비교시 빠르게 처리할 수 있으며 동일한 문자열은 한번만 저장되기 때문에 메모리 풋프린트도 감소한다. 리소스 데이터를 디스크에 저장하기 위해서는 ResourceId는 일반적으로 유효한 URL로 바뀐다.예를 들어 "texture:materials/granite.dds"와 같은 리소스 아이디는 실행시"file:///C:/Programme/[AppName]/export/textures/materials/granite.dds"로 바뀐다.
Resource 객체는 리소스 데이터를 위한 실제 컨테이너이다. 텍스쳐나 메쉬와 같은 특정 리소스 타입은 특별한 클래스 인터페이스를 가지는 Resource 클래스의 서브 클래스이다. Resource 서브 클래스는 D3D9Texture와 같이 종종 플랫폼이 종속적이기도 하지만 상황에 따라서는 Texture 클래스와 같이 플랫폼에 독립적이인 인터페이스를 가지기도 한다. Nebula2와는 다르게, 리소스 객체는 자신을 어떻게 설정하고 또 로딩하거나 저장하는지에 대해서 알지 못한다. 대신에 적절한 ResourceLoader나 ResourceSaver 객체가 해당 Resource 객체에 부착되어야 한다. Nebula 응용 프로그램은 데이터를 쓰는 일이 드물기 때문에ResourceSavers는 완전함을 위해 존재한다.(???) 다르게 이야기하면 ResourceLoaders가 중요한데 왜냐하면사용할 Resource 객체를 설정하는 유일한 방법이기 때문이다. ResourceLoaders 클래스는 리소스 설정 프로세스에대한 완전한 컨트롤 권한을 가진다. 이 클래스는 플랫폼에 한정될 수도 있고 관련한 플랫폼 Resource 클래스에 의존적일 수도있다. Nebula2와 비교하면 리소스의 설정에 대해서 더욱 많은 권한을 프로그래머에게 위임되었다. 예제 리소스 로더클래스들은StreamTextureLoader, StreamMeshLoader (스트림을 통해 텍스쳐와 메쉬를 설정한다.),MemoryVertexBufferLoader 그리고 MemoryIndexBufferLoader (메모리에서 정점 버퍼와 인덱스버퍼를 데이터로부터 설정한다.)이다.
Resource 클래스는 또한 동기 및 비동기 로딩에 대해서 공통된 인터페이스를 제공한다. 동기화된 로딩은 다음과 같다.
The SharedResourceServer싱글레톤 클래스는 ResourceId를 사용한 리소스의 공유 기능을 제공한다. SharedResourceServer를 통해서리소스를 생성하면 (이 리소스를 사용하는) 클라이언트의 회수에 상관없이 이 리소스는 한번만 로딩되어 메모리에 위치한다는 것이보장된다. 클라이언트의 회수가 0이 되면 해당 리소스는 자동으로 언로딩된다. (this is no substitute forproper resourcemanagement however, that's what the ResourceProxyServer cares about).리소스 공유는 Nebula3의 표준 객체 생성 메카니즘을 사용하여 직접 리소스 객체를 생성하는 방법으로 우회할 수도 있다.
A ResourceProxy (orManagedResource)클래스는 실제 리소스 객체에 대한 리소스 관리 래퍼 클래스이다. 이 아이디어가 필요한 이유는 포함된 리소스 객체가 리소스 사용피드백에 따른 리소스 매니저의 컨트롤에 의해서 변경될 수도 있기 때문이다. 예를 들어 텍스쳐 대리자는 요구한 텍스쳐가 백그라운드로딩되는 동안 placeholder 텍스쳐를 제공하거나 해당 리소스를 사용하는 모든 객체가 화면상에서 매우 작은 경우 저해상도의텍스쳐를 제공하기도 한다. 그리고 만약에 어떤 텍스쳐가 x 프레임동안 렌더링되지 않은 경우 그 텍스쳐를 언로드하는 등의 처리도텍스쳐 대리자에서 할수 있다. (역주: Gears of war 2와 같이 고해상도 텍스쳐를 사용하는 게임들은 존이 변경되거나 할 때 점진적으로 백그라운드 로딩을통해 텍스쳐를 읽어 들일 때 저해상도의 텍스쳐에서 고해상도로 부드럽게 변경하면서 읽어 들이는 것을 볼 수 있는데 이러한 처리를ResourceProxy 클래스에서 한다는 이야기)
The ResourceProxyServer (orResourceManager) 싱글레톤 클래스는 리소스 관리 시스템의 프론트엔드이다. ResourceProxy 클래스들의 팩토리 클래스이자 ResourceMappers 클래스와 리소스 타입을 결합시킨다. 다른 한편으로는 연결된 ResourceMappers에 대해서 기본적으로 모든 일을 관리한다.
The ResourceMapper클래스는 흥미를 유발하는 클래스이다. ResourceMapper는 텍스쳐나 메쉬와 같은 하나의 리소스 타입과 연관이 있는데애플리케이션은 이 ResourceMapper를 ResourceProxyServer에 연결한다. A ResourceMapper는렌더링 코드의 리소스 사용에 대한 피드백을 근거로 리소스의 로딩 및 언로딩을 이행한다. Subclasses ofResourceMapper 클래스의 서브 클래싱을 통해서 다른 리소스 관리 전략을 구현할 수도 있다. 그리고 특정ResourceMapper와 필요하다면 ResourceLoader의 서브 클래싱으로 완전히 커스터마이징하거나 플랫폼이나 응용프로그램에 한정된 리소스 관리 시나리오를 만드는 것도 가능하다. 이렇게 리소스 관리를 하는 것은 Nebula3의 리소스 관리목표가 필요한 것은 (미리) 모두 로딩하는 간단한 용도에서 큰 세계의 스트리밍 시나리오까지 모두 처리할 수 있는 뛰어난ResourceMappers 세트를 제공하는 것이기 때문이다.
렌더링 코드에서는 ResourceProxy 객체에 리소스 사용 피드백을 작성하는데 여기에는 리소스가 가까운 미래에도 필요한지 혹은 완전히 보이는지, 리소스를 사용하는 객체의 화면 공간의 크기에 대한 어림짐작(역주: 아마도 occlusion 계산을 위한 듯) 등의 내용을 포함해야 한다. The resource usage feedback is written by the rendering code toResourceProxy objects and should include stuff like whether theresource may be needed in the near future, whether the resource wasvisible at all, and a guesstimate of the screen space size of theobject using the resource. 그러나 ResourceProxy 서브 클래스에 의존하는 특정 피드백의 경우, ResourceProxy에 공통된 피드백 메소드가 존재하지 않는다.(???)
리소스 사용 피드백을 기준으로 ResourceMapper 다음의 작업을 실행할 수도 있다. (실제 작업 실행의 여부는 실제 매퍼에 전적으로 달려 있다)
여기까지다. 아주 간단한 리소스 관리(비동기로 필요한 리소스를 로딩하지만 스크린 크기나 자동으로 리소를 언로딩하는 것은 신경 쓰지 않는다.)를 포함하는 첫번째 코드를 릴리즈할 계획이다.
Nebula3 Resource subsystem
http://flohofwoe.blogspot.com/2007/05/nebula3-resource-subsystem.html
Nebula3의 Resource 서브시스템은 Nebula2와 비교할 때 더욱 열려 있으며 리소스의 생성과 관리에 대해서는 프로그래머에게 더 많은 권한을 위임하고 있다.
Nebula3의 리소스는 다음과 같은 속성을 가지고 있다.
- 다른 Nebula 서브시스템에서 필요로 하는 데이터를 랩(wrap)한다.
- ResourceId로 공유하는 것이 가능하다.
- 아무때나 초기화하거나 로딩, 언로딩하는 것이 가능해졌다.
- 동기 및 비동기 로딩이 가능하다.
저수준에서는 실제 리소스 객체와 리소스 공유, 로딩, 그리고 다소 중요도는 떨어지지만 저장과 같은 처리를 제공한다. 저수준의 리소스 클래스는 다음과 같다.
- ResourceId
- Resource
- ResourceLoader
- ResourceSaver
- SharedResourceServer
- ResourceProxy (대체 클래스 이름: ManagedResource)
- ResourceProxyServer (대체 클래스 이름: ResourceManager)
- ResourceMapper
ResourceId는 리소스에 대한 유일한 식별자이다. 리소스 아이디는 공유와 디스크 상에서의 리소스 데이터의 위치나 데이터 저장에 사용된다. ResourceId는 문자열 atom이다. Atom은 문자열 상수(혹은 다른 복잡한 데이터타입)에 대한 유니크한 32비트 식별자로 잦은 복사나 비교시 빠르게 처리할 수 있으며 동일한 문자열은 한번만 저장되기 때문에 메모리 풋프린트도 감소한다. 리소스 데이터를 디스크에 저장하기 위해서는 ResourceId는 일반적으로 유효한 URL로 바뀐다.예를 들어 "texture:materials/granite.dds"와 같은 리소스 아이디는 실행시"file:///C:/Programme/[AppName]/export/textures/materials/granite.dds"로 바뀐다.
Resource 객체는 리소스 데이터를 위한 실제 컨테이너이다. 텍스쳐나 메쉬와 같은 특정 리소스 타입은 특별한 클래스 인터페이스를 가지는 Resource 클래스의 서브 클래스이다. Resource 서브 클래스는 D3D9Texture와 같이 종종 플랫폼이 종속적이기도 하지만 상황에 따라서는 Texture 클래스와 같이 플랫폼에 독립적이인 인터페이스를 가지기도 한다. Nebula2와는 다르게, 리소스 객체는 자신을 어떻게 설정하고 또 로딩하거나 저장하는지에 대해서 알지 못한다. 대신에 적절한 ResourceLoader나 ResourceSaver 객체가 해당 Resource 객체에 부착되어야 한다. Nebula 응용 프로그램은 데이터를 쓰는 일이 드물기 때문에ResourceSavers는 완전함을 위해 존재한다.(???) 다르게 이야기하면 ResourceLoaders가 중요한데 왜냐하면사용할 Resource 객체를 설정하는 유일한 방법이기 때문이다. ResourceLoaders 클래스는 리소스 설정 프로세스에대한 완전한 컨트롤 권한을 가진다. 이 클래스는 플랫폼에 한정될 수도 있고 관련한 플랫폼 Resource 클래스에 의존적일 수도있다. Nebula2와 비교하면 리소스의 설정에 대해서 더욱 많은 권한을 프로그래머에게 위임되었다. 예제 리소스 로더클래스들은StreamTextureLoader, StreamMeshLoader (스트림을 통해 텍스쳐와 메쉬를 설정한다.),MemoryVertexBufferLoader 그리고 MemoryIndexBufferLoader (메모리에서 정점 버퍼와 인덱스버퍼를 데이터로부터 설정한다.)이다.
Resource 클래스는 또한 동기 및 비동기 로딩에 대해서 공통된 인터페이스를 제공한다. 동기화된 로딩은 다음과 같다.
- res-> SetResourceId("tex:system/white.dds");
- res-> SetLoader(StreamTextureLoader::Create());
- res-> SetAsyncEnabled(false)
- res-> Load()
- if (res-> IsValid()) ... 리소스 로딩에 성공했다. 성공하지 못한 경우 LoadFailed()는 참을 리턴하게 된다.
- res->SetResourceId("tex:system/white.dds");
- res->SetLoader(StreamTextureLoader::Create());
- res->SetAsyncEnabled(true);
- res->Load();
- 리소스는 이제 로딩 상태가 된다.
- aslong as IsPending() 함수가 참을 반환하는한 반복해서 Load()를 호출한다. 물론 실제 애플리케이션에서는 그 동안 의미 있는 작업을 하겠지만...
- Load() 함수를 호출한 후 어느 시점에서 리소스의 상태는 Valid(리소스가 사용 가능하도록 준비된 상태)나 Failed(리소스 로딩에 실패한 경우) 혹은 Cancelled(로딩 중 취소한 경우) 중 하나가 된다.
The SharedResourceServer싱글레톤 클래스는 ResourceId를 사용한 리소스의 공유 기능을 제공한다. SharedResourceServer를 통해서리소스를 생성하면 (이 리소스를 사용하는) 클라이언트의 회수에 상관없이 이 리소스는 한번만 로딩되어 메모리에 위치한다는 것이보장된다. 클라이언트의 회수가 0이 되면 해당 리소스는 자동으로 언로딩된다. (this is no substitute forproper resourcemanagement however, that's what the ResourceProxyServer cares about).리소스 공유는 Nebula3의 표준 객체 생성 메카니즘을 사용하여 직접 리소스 객체를 생성하는 방법으로 우회할 수도 있다.
A ResourceProxy (orManagedResource)클래스는 실제 리소스 객체에 대한 리소스 관리 래퍼 클래스이다. 이 아이디어가 필요한 이유는 포함된 리소스 객체가 리소스 사용피드백에 따른 리소스 매니저의 컨트롤에 의해서 변경될 수도 있기 때문이다. 예를 들어 텍스쳐 대리자는 요구한 텍스쳐가 백그라운드로딩되는 동안 placeholder 텍스쳐를 제공하거나 해당 리소스를 사용하는 모든 객체가 화면상에서 매우 작은 경우 저해상도의텍스쳐를 제공하기도 한다. 그리고 만약에 어떤 텍스쳐가 x 프레임동안 렌더링되지 않은 경우 그 텍스쳐를 언로드하는 등의 처리도텍스쳐 대리자에서 할수 있다. (역주: Gears of war 2와 같이 고해상도 텍스쳐를 사용하는 게임들은 존이 변경되거나 할 때 점진적으로 백그라운드 로딩을통해 텍스쳐를 읽어 들일 때 저해상도의 텍스쳐에서 고해상도로 부드럽게 변경하면서 읽어 들이는 것을 볼 수 있는데 이러한 처리를ResourceProxy 클래스에서 한다는 이야기)
The ResourceProxyServer (orResourceManager) 싱글레톤 클래스는 리소스 관리 시스템의 프론트엔드이다. ResourceProxy 클래스들의 팩토리 클래스이자 ResourceMappers 클래스와 리소스 타입을 결합시킨다. 다른 한편으로는 연결된 ResourceMappers에 대해서 기본적으로 모든 일을 관리한다.
The ResourceMapper클래스는 흥미를 유발하는 클래스이다. ResourceMapper는 텍스쳐나 메쉬와 같은 하나의 리소스 타입과 연관이 있는데애플리케이션은 이 ResourceMapper를 ResourceProxyServer에 연결한다. A ResourceMapper는렌더링 코드의 리소스 사용에 대한 피드백을 근거로 리소스의 로딩 및 언로딩을 이행한다. Subclasses ofResourceMapper 클래스의 서브 클래싱을 통해서 다른 리소스 관리 전략을 구현할 수도 있다. 그리고 특정ResourceMapper와 필요하다면 ResourceLoader의 서브 클래싱으로 완전히 커스터마이징하거나 플랫폼이나 응용프로그램에 한정된 리소스 관리 시나리오를 만드는 것도 가능하다. 이렇게 리소스 관리를 하는 것은 Nebula3의 리소스 관리목표가 필요한 것은 (미리) 모두 로딩하는 간단한 용도에서 큰 세계의 스트리밍 시나리오까지 모두 처리할 수 있는 뛰어난ResourceMappers 세트를 제공하는 것이기 때문이다.
렌더링 코드에서는 ResourceProxy 객체에 리소스 사용 피드백을 작성하는데 여기에는 리소스가 가까운 미래에도 필요한지 혹은 완전히 보이는지, 리소스를 사용하는 객체의 화면 공간의 크기에 대한 어림짐작(역주: 아마도 occlusion 계산을 위한 듯) 등의 내용을 포함해야 한다. The resource usage feedback is written by the rendering code toResourceProxy objects and should include stuff like whether theresource may be needed in the near future, whether the resource wasvisible at all, and a guesstimate of the screen space size of theobject using the resource. 그러나 ResourceProxy 서브 클래스에 의존하는 특정 피드백의 경우, ResourceProxy에 공통된 피드백 메소드가 존재하지 않는다.(???)
리소스 사용 피드백을 기준으로 ResourceMapper 다음의 작업을 실행할 수도 있다. (실제 작업 실행의 여부는 실제 매퍼에 전적으로 달려 있다)
- Load: 특정한 LOD(level-of-detail )에서의 비동기 로딩 (예를 들면 필요하지 않는 경우 고해상도의 밉맵을 건너뛰는 것과 같은 것)하고 로딩중인 리소스에 대한 placeholder를 제공한다.
- Unload: 리소스를 완전히 언로드 시키고 메모리를 해제한다.
- Upgrade: 이미 로드한 리소스의 LOD 레벨을 증가시킨다.(예를 들어 텍스쳐의 고해상도의 밉맵 레벨을 로딩하는 것)
- Degrade: 로드한 리소스의 LOD 레벨을 감소시킨다. (예를 들어 텍스쳐의 고해상도 밉맵 레벨을 떨어뜨리는 일)
여기까지다. 아주 간단한 리소스 관리(비동기로 필요한 리소스를 로딩하지만 스크린 크기나 자동으로 리소를 언로딩하는 것은 신경 쓰지 않는다.)를 포함하는 첫번째 코드를 릴리즈할 계획이다.
# by | 2009/02/05 10:54 | Nebula Device | 트랙백 | 핑백(1) | 덧글(0)
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
... 번역해 놓은 포스팅이 있어 올립니다. Nebula3를 이해하기 위한 가장 중요한 포스팅들입니다. Nebula3 Render Layer : CoreGraphicsNebula3 Resource subsystemNebula3 Graphics subsystemNebula3 Application Layer작년 8월에 소스 코드가 릴리즈 되었을 때 올 2월 쯤에 애니메 ... more