
-
Metal 4 게임 알아보기
Metal 4의 최신 개선 사항으로 게임 엔진을 최적화하는 법을 살펴보세요. CPU 오버헤드를 최소화하고, 방대한 장면을 지원하기 위한 그래픽 리소스 관리를 확장하며, 메모리 한도를 극대화하고, 대규모 파이프라인 상태 라이브러리를 빠르게 로드하는 방법을 확인합니다. 이 세션을 최대한 활용하려면 ‘Metal 4 살펴보기'를 먼저 시청하는 것이 좋습니다.
챕터
- 0:00 - 서론
- 1:33 - 더 효율적으로 인코딩하기
- 8:42 - 리소스 관리 확장하기
- 17:24 - 파이프라인 빠르게 로드하기
- 31:25 - 다음 단계
리소스
- Human Interface Guidelines: Designing for games
- Metal binary archives
- Reading and writing to sparse textures
- Resource synchronization
- Synchronizing resource accesses between multiple passes with a fence
- Synchronizing resource accesses with earlier passes with a consumer-based queue barrier
- Synchronizing resource accesses with subsequent passes with a producer-based queue barrier
- Synchronizing resource accesses within a single pass with an intrapass barrier
- Understanding the Metal 4 core API
- Using a render pipeline to render primitives
- Using the Metal 4 compilation API
관련 비디오
WWDC25
- 게임 수준 높이기
- 몰입감 넘치는 앱을 위한 Metal 렌더링의 새로운 기능
- Metal 4 게임 심화 기능 알아보기
- Metal 4 머신 러닝과 그래픽 결합하기
- Metal 4 살펴보기
Tech Talks
-
비디오 검색…
안녕하세요, 저는 Jason입니다 저는 Yang입니다 저희는 GPU 드라이버 엔지니어입니다 이 동영상에서는 Metal 4로 게임 엔진을 가속화하는 방법을 소개합니다 본 세션은 4편 중 두 번째로, Metal API의 다음 주요 버전을 소개합니다 Metal 4 게임을 알아보기 전에 'Metal 4 살펴보기'를 시청해 주요 기능을 먼저 확인해 주세요 이후 'Metal 4 게임 심화 기능 알아보기'를 시청해 새 Metal FX와 Metal 광선 추적 API를 알아봅니다 그 후 ML 통합을 다룬 'Metal 4 머신 러닝'을 시청하세요 Metal 4를 살펴봅시다
Metal 4는 최신 게임 엔진을 위해 설계되었습니다 Ubisoft의 어쌔신 크리드 섀도우스와 같은 게임은 플레이어가 환상적 세계에 몰입하도록 정교한 풍경을 자세히 그려 냅니다 기가바이트 규모의 세부적인 지오메트리와 텍스처를 스트리밍하고 수천 개의 셰이더로 렌더링해 Apple Silicon에서 모든 컴퓨팅 성능을 활용합니다 미래의 게임은 지금보다 더욱 많은 것을 요구할 것이며 작업에 맞게 확장 가능한 그래픽 API가 필요합니다 바로 Metal 4가 그것이죠
Metal 4에는 게임에 대한 중요 개선 사항이 포함됩니다 여기에는 효율적인 명령 인코딩 핵심 경로 속도를 높이기 위한 확장된 리소스 관리와 더 빠른 파이프라인 로딩이 포함되어서 플레이어가 로딩 화면에서 나와 게임에 몰입하도록 합니다 이번 세션에서는 동료와 함께 이 기능의 활용 방법을 알아봅니다 게임의 모든 프레임에서 드로우 호출, 커널 디스패치, 블릿 및 레이 트레이싱 작업 모두 인코딩의 핵심 경로에 포함됩니다 Metal 4 인코딩은 이러한 과제를 효율적이고 동시적으로 해결하도록 설계되었습니다
Metal 4는 가장 일반적인 작업을 두 가지 인코더 클래스로 통합해 각 인코더로 더 많은 작업을 수행할 수 있습니다 명령 할당자를 사용하면 인코딩하는 동안 발생한 메모리 할당을 명시적으로 관리할 수 있습니다 명령 버퍼로 여러 스레드 전반의 작업을 인코딩할 수 있습니다
'Metal 4 살펴보기'에서 두 인코더 클래스 render와 compute의 모든 명령 처리 방법을 설명했습니다 효율적으로 사용하려면 컴퓨팅 연산 간의 데이터 종속성을 동기화해야 하고 첨부 맵을 사용해 프래그먼트 셰이더 출력을 다시 매핑합니다 모든 컴퓨팅 연산, 커널 디스패치, 블릿 및 가속 구조 빌드 작업을 이제 하나의 컴퓨팅 인코더에서 인코딩할 수 있습니다 추가적인 동기화 없이 이러한 명령은 동시에 실행됩니다 그러면 종속성 없는 워크로드가 GPU 리소스를 잘 활용할 수 있습니다. 데이터 종속성으로 인해 패스의 일부 명령을 직렬로 실행해야 하면 패스 배리어를 통해 표현할 수 있습니다 이 배리어는 GPU가 해당 인코더에서 이전에 수행된 모든 블릿 작업이 완료될 때까지 대기하고 이후에 컴퓨팅 디스패치 작업을 시작하도록 보장합니다 비트에서 디스패치로의 액세스 동기화 방법의 예제로 먼저 copyFromBuffer 블릿은 buffer1을 업데이트해 패스 배리어를 인코딩합니다 그리고 buffer1에 있는 데이터를 사용하는 디스패치를 인코딩할 수 있습니다 통합된 컴퓨팅 인코딩이죠 모든 컴퓨팅 작업을 하나의 인코더에서 수행하고 배리어로 데이터 종속성을 표현합니다 Metal 4에서는 렌더링 인코딩도 업데이트되었습니다 색상 첨부 매핑을 사용하면 이제 렌더링 파이프라인의 색상 출력과 렌더링 인코더 첨부 사이의 대응 관계를 제어할 수 있습니다 파이프라인을 고정된 렌더링 대상 레이아웃에 바인딩하는 대신 색상 첨부 맵을 제공할 수 있습니다 이후 새 파이프라인을 설정하면 인코더를 전환하는 대신 맵을 변경할 수 있습니다 fragment 함수가 있는 Metal 파이프라인이 있으며 세 가지 첨부에 출력한다고 가정합니다 색상 첨부 매핑 없이 세 가지 첨부로 렌더딩 인코더를 생성합니다 fragment 함수는 세 가지 출력을 반환하고 인코더는 해당 출력을 타일 메모리의 해당 첨부로 연결합니다 다음 드로우 호출의 경우 다른 출력 세트에 작성하는 파이프라인이 필요할 수 있습니다 첨부가 다르기 때문에 색상 출력과 일치하려면 새 렌더링 인코더를 만들어야 합니다 색상 첨부 매핑을 사용하면 둘째 인코더가 필요하지 않습니다 대신 렌더링 인코더에는 두 파이프라인에 필요한 모든 색상이 있습니다. 그 다음 색상 첨부 맵은 셰이딩 출력을 특정 첨부로 변환합니다. 색상 첨부 매핑을 구현하려면 색상 첨부 매핑을 지원하는 패스 설명자 렌더링을 설정해 시작합니다 그런 다음 인코더에서 사용할 첨부의 전체 상위 집합을 만듭니다 인코더가 어떤 첨부를 그릴지 구성하려면 색상 첨부 맵을 만든 다음 다시 매핑 항목을 설정합니다 각 항목에 대해 셰이더 출력을 결정하는 논리적 인덱스와 첨부 인덱스를 결정하는 물리적 인덱스를 결정합니다 인코딩 전에 이 매핑 오브젝트를 구성하고 프레임마다 재사용합니다 렌더링 파이프라인을 설정할 때 색상 첨부 맵도 바인딩합니다 파이프라인이 다른 첨부에 드로우하면 다른 색상의 첨부 맵으로 전환할 수 있습니다 색상 첨부 매핑을 통해 게임의 렌더링 인코더 수를 크게 줄일 수 있습니다 이렇게 하면 렌더링 패스의 양을 줄여 인코딩 오버헤드가 감소하고 GPU 효율성이 향상됩니다
Metal 4에서는 메모리 할당에 대한 더 많은 제어를 제공합니다
명령 할당자를 통해 명령 버퍼 메모리를 재사용하고 인코딩하는 동안 동적 할당을 방지할 수 있습니다 명령을 인코딩하면 할당자 메모리가 증가합니다 연관된 GPU 명령의 실행이 완료되면 할당자를 재설정합니다 재설정은 명령 메모리를 나중에 명령 인코딩에 재사용할 수 있게 합니다. 여러 할당자를 사용해 인코딩 차단을 방지할 수 있으며 동시에 GPU 작업을 완료합니다 새로운 명령 할당자에 인코딩하면 인코딩된 명령에 대한 메모리를 할당합니다 이 명령 메모리는 GPU에서 실행되는 작업입니다 따라서 재설정하기 전에 커밋한 작업이 완료될 때까지 기다립니다 GPU 작업이 완료되면 명령 할당자를 재설정합니다 그러면 해당 메모리가 즉시 재사용 가능으로 표시됩니다 GPU 작업이 실행되는 동안 인코딩을 계속하려면 두 번째 명령 할당자를 사용합니다 이를 통해 GPU 작업 완료 후 인코딩 차단이 방지됩니다 GPU 작업이 완료되면 명령 할당자를 재설정해야 합니다 할당자 메모리는 재설정될 때까지 인코딩 지원을 위해 증가합니다 명령 할당자에서 더 이상 작업을 인코딩할 계획이 없으면 해제해 메모리 사용 공간을 줄일 수 있습니다 명령 할당자는 스레드 안전을 지원하지 않으므로 스레드마다 다른 할당자를 사용합니다 이 기능은 장면 인코딩을 병렬화할 때 중요합니다 Metal 4 명령 버퍼로 인코딩을 여러 스레드에 분할할 수 있습니다. 단일 스레드 인코딩에서 일련의 명령을 순서대로 하나 이상의 명령 버퍼에 인코딩합니다 Apple Silicon 멀티코어 CPU의 강점을 활용하고 여러 스레드에서 각각 다른 명령 할당자를 사용해 여러 명령 버퍼를 시작합니다 Metal 4의 컴퓨팅 인코더의 향상된 유연성을 사용해 블릿, 디스패치 및 가속 구조화 작업의 인코딩을 고르게 분산할 수 있는 유연성을 제공합니다 명령 버퍼 인코딩을 마치면 한 번의 커밋 호출로 모든 것을 제출할 수 있습니다 Metal 4에서 GPU의 단일 패스로 여러 렌더링 인코더를 커밋할 수도 있습니다 인코딩에 오랜 시간이 걸리는 렌더링 패스가 있다고 가정합시다 기본적으로 인코딩을 개별 렌더링 인코더로 나누면 GPU는 이를 별도의 렌더링 패스로 실행합니다 각 패스는 중간 결과 저장 및 로드 시 오버헤드가 발생합니다
Metal 4는 일시 중단/재개 옵션을 제공해 여러 렌더링 인코더를 병합합니다. 하나의 명령 버퍼에서 렌더링 인코더를 일시 중단하고 다른 명령 버퍼에서 재개하면 됩니다 명령 버퍼 인코딩이 완료되면 단일 커밋 호출에서 순차적으로 제출합니다 렌더링 인코더를 한 번에 제출하면 Metal이 렌더링 패스를 병합합니다 구현하려면 일시 중단 옵션으로 첫 번째 인코더를 만듭니다 Metal은 이 인코더를 미래 인코더와 통합합니다 인코더마다 다른 명령 버퍼를 사용합니다 중간 인코더에는 재개 및 일시 중단 옵션이 모두 있습니다 재개 옵션만 있는 최종 인코더를 만듭니다 세 개의 인코딩된 명령 버퍼를 모두 커밋합니다 끝났습니다 이제 렌더링 패스가 병합되었습니다 Metal 4를 사용하면 인코더 수를 줄여 효율성을 높일 수 있으며, 명령 메모리를 재사용하고 여러 스레드 전반에 인코딩합니다 Metal 4 명령 인코딩에 대해 자세히 알아보려면 Apple 개발자 사이트의 문서를 참고하세요 이제 효율적인 인코딩에 대해 다루었으므로 효율적인 리소스 관리에 대해 자세히 알아보겠습니다 Metal 4에는 대규모 리소스를 관리하는 데 도움이 되는 몇 가지 흥미로운 새 기능이 있습니다 인수 테이블 및 레지던시 세트를 사용하면 리소스 바인딩을 수천 개의 리소스로 확장할 수 있습니다 Metal 4에서 사용자가 드로어블 리소스를 관리하고 종속성에 대한 제어 권한을 제공합니다 대기열 배리어는 대규모 리소스 종속성의 표현 방법을 제공합니다 텍스처 보기 풀과 배치 스파스 힙은 대형 리소스에 필요한 메모리를 관리하는 데 도움을 줍니다 셰이더의 복잡성 증가는 바인드리스 모델이 리소스 수량에 적합함을 의미합니다 단일 인수 버퍼로 셰이더는 버퍼, 텍스처, 샘플러 파이프라인 상태 등 수천 개의 리소스에 접근할 수 있습니다 하지만 인덱스된 바인드 포인트는 루트 수준 리소스를 바인드하는
데 사용됩니다. 인수 테이블을 사용해 인덱스별로 리소스를 바인드합니다. 인코딩하는 동안 다음 드로우 또는 디스패치에 사용할 인수 테이블을 설정합니다 이러한 리소스는 인덱스된 함수 인수로 셰이더에 제공됩니다 드로우와 디스패치 시점에 Metal은 인수를 수집합니다 즉, 드로우 호출 사이에 새 리소스를 바인드 인덱스로 설정하는 것이 안전합니다 단일 인수 테이블은 여러 인코더 단계에서 설정될 수 있습니다
인코딩 전에 인수 테이블을 생성하면 리소스 바인딩을 중요 경로 밖으로 이동할 수 있습니다 하나의 인수 테이블을 여러 인코더에 연결할 수 있습니다 인수 버퍼와 함께 인수 테이블을 사용해 리소스 바인딩 요구를 확장합니다 셰이더에서 이 리소스에 접근하기 위한 다음 단계는 GPU를 볼 수 있도록 만드는 것입니다 GPU에 리소스가 필요할 때마다 레지던시 세트에 추가합니다 파이프라인, 버퍼, 텍스처 드로어블이 포함됩니다 레지던시 세트를 사용하면 여러 리소스를 함께 그룹화하고 모두 동시에 표시되도록 만들 수 있습니다 커밋되는 명령 버퍼에 첨부하거나 명령 대기열에 직접 첨부합니다 레지던시 세트가 시간이 지나도 크게 변하지 않으면 명령 대기열에 첨부하는 것을 선호합니다 레지던시 세트가 자주 변경되면 적절한 명령 버퍼에 연결합니다 GPU에 대형 리소스 준비가 시간이 걸릴 수 있습니다 세트의 리소스가 미리 상주하도록 Metal에 요청할 수 있습니다 레지던시 세트는 줄이고 각각 더 많은 리소스 할당을 선호합니다 Metal이 리소스를 대량으로 처리해 성능이 향상됩니다 레지던시 세트에 대해 알아보려면 Apple 개발자 사이트의 문서와 작년의 "Apple 플랫폼으로 고사양 게임 포팅하기" 세션을 참고합니다 Metal 4로 리소스 상주를 제어하면 게임의 드로어블 표면에도 적용됩니다 게임의 렌더링된 콘텐츠를 디스플레이로 전송하려면 CAMetalLayer에서 드로어블 표면에 렌더링합니다 각 Metal 레이어는 동적 레지던시 세트를 유지 관리합니다 레이어의 모든 텍스처를 상주시키려면 명령 대기열에 추가합니다. 레지던시 세트는 한 번만 추가하면 됩니다 CAMetalLayer는 필요할 때 업데이트합니다 Metal 4에서는 렌더링을 드로어블과 동기화해야 합니다 각 프레임 동안 다음 드로어블을 가져온 후 드러어블에 렌더링하기 전에 명령 대기열에서 대기하도록 인코딩합니다 그런 후 렌더링 작업을 커밋하고 신호를 대기열의 드로어블에 인코딩합니다
렌더링 완료 시 present를 호출해 프레임 내용을 디스플레이로 보냅니다. 추적 오버헤드를 줄이려면 Metal 4에서 리소스를 동기화할 수 있습니다 본 세션의 앞부분에서 인코더 내 패스 배리어 사용 방법을 설명했습니다. 반면 대기열 배리어는 동일한 대기열의 인코더에서 데이터 종속성을 표현합니다
배리어는 Metal 단계별로 필터링됩니다 인코더의 각 명령은 하나 이상의 실행 단계와 연관됩니다 예를 들어, 렌더링 인코더의 드로우 호출은 꼭짓점과 프래그먼트 셰이딩 단계를 모두 생성합니다 Apple Silicon GPU는 모든 꼭짓점 작업을 일괄 처리한 후 모든 프래그먼트 셰이딩 작업이 이어집니다 Metal 4의 컴퓨팅 명령은 디스패치, 블릿 및 가속화 구조 단계에 해당합니다 과도한 동기화를 피할 수 있는 적절한 단계를 선택해야 합니다 이 예에서 컴퓨팅 패스는 커럴 디스패치에서 대기 시뮬레이션을 수행합니다 결과는 메모리의 텍스처에 기록됩니다 렌더링 패스는 장면을 그립니다 프래그먼트 셰이딩에서 시뮬레이션 결과는 조명과 블렌드되어야 하지만 꼭짓점 작업은 컴퓨팅 작업과 겹쳐져야 합니다. 시뮬레이션 결과에 대한 접근을 동기화하려면 대기열의 디스패치 단계에서 렌더링 인코더의 프래그먼트 단계로 배리어를 인코딩합니다 이 예를 구현하려면 컴퓨팅 인코더에서 디스패치 인코딩을 시작합니다 그런 다음 렌더링 명령 인코더에서 대기열 단계의 디스패치 후와 프래그먼트 단계 전에 배리어를 추가합니다 배리어 이후 드로우 호출을 인코딩할 수 있습니다 Metal은 현재 렌더링 인코더와 추후 인코더에서 이전 인코더의 모든 디스패치 단계 작업이 완료될 때까지 모든 프래그먼트 단계의 작업이 실행되지 않도록 합니다
배리어에 최적인 장소를 찾는 데 도움이 되도록 Metal 디버거는 해당 위치를 보여주고 어떤 인코더와 어떤 단계에 적용되는지도 알려 줍니다 이를 사용해 데이터 종속성을 유지하면서 동시성을 극대화합니다
Metal 배리어 사용으로 리소스를 동기화하는 방법은 Apple 개발자 사이트에서 전체 문서를 살펴보세요
텍스처 및 버퍼 스트리밍을 통해 수천 개의 리소스에 대한 메모리 사용량을 관리할 수 있습니다 Metal 4로 버퍼와 텍스처를 효율적으로 스트리밍합니다 배치 스파스를 사용해 경량의 텍스처 보기를 생성하고 메모리 리소스 사용 공간을 관리할 수 있습니다 현대적인 게임은 수백 가지의 텍스처와 프레임당 텍스처 버퍼 보기를 생성할 수 있습니다 TextureViewPools를 사용하면 필요한 메모리를 미리 할당해 모든 텍스처 보기를 포함할 수 있습니다 그리고 풀의 인덱스에서 경량의 텍스처 보기를 생성할 수 있죠 동적 할당이 발생하지 않으므로 인코딩 중에 생성할 수 있습니다 텍스처 보기의 리소스 ID를 사용해 인수 버퍼 또는 인수 테이블에 바인딩합니다 구현 방법은 이렇습니다 인코딩 시간에 앞서 텍스처 보기 풀을 생성합니다 생성된 텍스처 보기 풀에는 500개의 텍스처 보기에 대한 메모리가 할당됩니다 인코딩하면 텍스처 보기 풀의 원하는 인덱스에서 텍스처 보기를 설정합니다 반환된 MTLResourceID 사용으로 텍스처 보기를 인수 테이블에 바인딩합니다 바인딩하는 데 필요한 리소스가 큰 메모리 사용 공간을 차지할 수 있습니다. 스파스 리소스는 메모리에 동시에 들어갈수 없는 고충실도 리소스에 적합니다 리소스 생성을 메모리 백업에서 분리하거든요 배치 스파스에서는 리소스가 힙의 페이지에 매핑되는 방식을 제어할 수 있습니다 리소스에 대한 메모리 매핑을 업데이트하면 Metal 4 명령 대기열의 API를 사용하면 이 업데이트를 다른 GPU 작업과 동기화할 수 있습니다. 배치 힙의 메모리는 타일 시퀀스로 구성됩니다 스파스 버퍼와 텍스처에 대한 이 타일의 할당을 제어합니다 바이트 범위 또는 픽셀 지역을 매핑해 메모리 사용으로 스파스 리소스를 제공합니다
배치 힙을 생성하면 리소스에 필요한 스파스 페이지 크기를 고려합니다 매핑 및 매핑 해제 작업 중에 대형 페이지 크기에는 몇 가지 성능 이점이 있지만 패딩과 정렬에 더 많은 메모리가 사용됩니다 힙은 지정한 최대 크기까지 모든 스파스 페이지 크기를 지원합니다 이 예에서는 최대 페이지 크기를 64KB로 선택합니다 배치 힙을 생성하면 스파스 리소스를 생성할 수 있습니다. 배치 스파스 버퍼 및 텍스처 생성은 비 스파스 리소스와 유사하게 Metal 기기에서 수행됩니다 버퍼의 경우 요청된 버퍼 크기를 스파스 타일 크기의 배수에 맞춥니다. 기기는 이 변환을 수행하기 위한 쿼리를 제공합니다 길이를 사용하거나 텍스처 설명자에서 새 버퍼를 호출할 때 배치 스파스 페이지 크기를 설정합니다 이 속성은 배치 힙이 메모리 지원을 제공하는 Metal 기기에 대한 정보를 제공하죠 처음 배치 스파스 버퍼를 생성할 때 이를 지원하는 메모리는 없습니다 업데이트 매핑 작업을 통해 타일을 버퍼 범위에 할당합니다 배치 힙에서 타일을 버퍼에 할당하려면 먼저 업데이트 매핑 작업을 지정해야 합니다 시작 오프셋 및 길이와 힙의 타일 오프셋을 제공해 이 버퍼 범위에 할당하고 Metal 4 명령 대기열의 매핑 작업을 제출합니다
스파스 리소스 작업에 대해 알아보려면 Apple Developer 웹사이트의 문서를 참고하세요 현대 게임에 대한 또 다른 도전은 파이프라인 상태의 대형 라이브러리를 관리하는 것입니다 이제 Yang이 이어서 설명하겠습니다 Jason님, 고맙습니다 현대 게임은 수천 개의 파이프라인을 생성해 복잡하고 역동적인 비주얼을 만들어야 합니다 많은 파이프라인을 빠르게 로드하는 것은 셰이더 완료 끊김을 제거하고 게임 로딩 시간을 단축하는 데 중요합니다 Metal 4에서 파이프라인을 빠르게 로드하려면 렌더링 파이프라인 컴파일을 재사용할 수 있습니다. 기기에서 새 수준의 병렬 처리로 파이프라인을 컴파일할 수도 있고 파이프라인을 미리 컴파일하면 파이프라인 로딩 시간을 거의 0으로 줄일 수 있습니다 먼저 유연한 렌더링 파이프라인 상태로 랜더링 파이프라인 컴파일 재사용 방법을 보여드리죠 도시 건설 게임을 만든다고 가정해 보겠습니다 여기서 플레이어는 지도 주변에 집을 배치할 수 있습니다 플레이어가 집을 배치할 위치를 결정하면 게임은 홀로그램 스타일로 집을 렌더링해야 합니다 그래서 추가 블렌드 상태의 파이프라인이 필요합니다 플레이어가 집을 배치하면 집을 짓기 시작합니다 집을 투명하게 렌더링하고 건축 진행 상황을 보여주려면 투명 블렌드 상태의 또 다른 파이프라인이 필요합니다 마침내 집이 완성되면 불투명한 블렌드 상태의 세 번째 파이프라인으로 집을 렌더링합니다 생성 시 전체 파이프라인 구성을 제공해 세 개의 파이프라인을 전체 상태로 컴파일할 수 있습니다 vertex 함수와 fragment 함수 부터 시작합니다 불투명, 반투명, 홀로그램 집을 위한 색상 첨부부터 시작해 보죠 여기서 색상 첨부 구성은 설명자의 일부를 의미하며 색상 첨부의 프래그먼트 셰이더 출력 작성에 영향을 줍니다 여기에 첨부 파일의 픽셀 형식 올바른 마스크와 블렌드 상태가 포함됩니다 vertex 함수, fragment 함수 불투명 구성을 참조하는 렌더링 파이프라인 설명자를 생성합니다 해당 설명자를 사용해 vertex 바이너리, fragment 바이너리 바디, fragment 출력 부분을 포함한 불투명 파이프라인을 생성합니다 설명자에서 색상 첨부 구성을 바꿔 마찬가지로 투명 파이프라인 홀로그램 파이프라인을 만들 수 있어요 이 세 파이프라인에서 대부분의 바이너리는 동일하며 fragment 출력 부분만 다릅니다 CPU 타임라인 보기에서 전체 불투명 파이프라인 투명한 파이프라인, 홀로그램 파이프라인을 차례로 컴파일합니다 CPU는 거의 같은 파이프라인을 다시 컴파일하는 데 더 많은 시간을 소모합니다. fragment 출력 부분은 제외하고요 Metal 4로 먼저 특화되지 않은 파이프라인을 생성해 이제 대부분의 파이프라인 완성본을 재사용할 수 있습니다 그런 후 다른 색상 첨부 구성을 사용해 필요한 최종 특화된 파이프라인을 가져옵니다 그러면 렌더링 파이프라인 완료 시간을 많이 줄일 수 있습니다 비용 절감을 위해 먼저 특화되지 않은 파이프라인을 생성합니다 같은 설명자로 시작하지만 실제 색상 첨부 구성을 제공하는 대신 모든 필드를 특화되지 않음으로 설정합니다 이를 위해, 모든 색상 첨부 설명자를 반복하기만 하면 되고 pixelFormat writeMask blendingState를 특화되지 않은 값으로 설정합니다 특화되지 않은 파이프라인에는 vertex 바이너리, fragment 바디, 기본 fragment 출력 부분이 포함됩니다 기본 fragment 출력은 일부의 경우에 작동하지만 대부분의 경우 파이프라인을 특화해 교체해야 합니다 특화된 파이프라인을 생성하려면 특화되지 않은 파이프라인과 새 렌더링 파이프라인 설명자로 시작합니다. 이때 설명자의 색상 첨부 구성을 필요한 실제 값으로 설정합니다 특화된 파이프라인에는 기본 fragment 출력을 대체하는 fragment 출력이 포함되어 있습니다 새 fragment 출력은 매우 빠르게 생성될 수 있으므로 전체 셰이더 컴파일 프로세스를 다시 수행할 필요가 없습니다 투명한 파이프라인을 특화하는 예로 돌아가보죠 먼저 설명자에서 이전에 특화되지 않은 특성을 설정합니다 블렌딩 상태를 활성화하고 블렌딩 하위 상태를 설정합니다 여기의 코드는 파이프라인이 미리 곱해진 알파 블렌딩을 수행하도록 설정합니다. 그런 다음 특화되지 않은 파이프라인으로 새 설명자를 사용해 특화된 파이프라인을 인스턴스화합니다 게임은 수천 개의 스테이트풀 렌더링 파이프라인을 생성할 수 있습니다. 로드 시간 단축을 최대화하려면 특화되지 않은 모든 렌더링 파이프라인을 생성하고 나중에 필요에 따라 특화할 수 있습니다 그러면 GPU 성능에 약간의 오버헤드가 발생할 수 있습니다 많은 오버헤드는 공유된 fragment 바디의 불필요한 작업에서 발생할 수 있습니다 예를 들어, 프래그먼트 셰이더가 4개의 색상 채널에 작성하고 색상 첨부에 한 채널만 있으면 컴파일러는 더 이상 사용되지 않는 채널을 최적화할 수 없죠 또한, fragment 바이너리 바디에서 fragment 출력 부분으로 이동 시 작은 오버헤드가 발생합니다 이 오버헤드는 보통 작지만 일부 프래그먼트 셰이더에서는 클 수 있습니다. 중요한 셰이더를 식별하고 백그라운드에서 전체 상태로 컴파일하면 플레이어는 짧은 로드 시간과 놀라운 프레임 속도를 즐길 수 있죠 Instruments의 Metal 시스템 추적을 사용해 가장 고가의 특화된 프래그먼트 셰이더 순위를 정할 수 있습니다. 요약하자면 유연한 렌더링 파이프라인 상태를 게임에 효과적으로 통합하는 방법입니다 모든 렌더링 파이프라인을 특화되지 않은 상태로 먼저 컴파일하고 필요에 따라 특화하세요 눈에 띄는 성능 저하가 있으면 Instrument의 Metal 시스템 추적을 사용해 게임 프로파일링하고 중요한 파이프라인을 식별합니다 중요한 파이프라인의 경우 백그라운드에서 고정된 버전을 컴파일하고 특화된 버전이 준비되면 대체해 사용합니다 유연한 렌더링 파이프라인 상태에 대해 자세히 알아보려면 Apple Developer 웹사이트 문서를 참고하세요
유연한 렌더링 파이프라인 상태로 파이프라인 컴파일을 재사용한 후 고유한 기기 컴파일을 병렬화해 파이프라인 로드 시간을 줄입니다 일부 게임은 게임플레이 중에 파이프라인 로드를 위해 단일 스레드를 사용할 수 있습니다 게임이 사용할 파이프라인을 빌드하는 단일 컴파일 스레드죠 그리고 여기에 인코딩과 같은 반복적인 프레임 렌더링 작업을 수행하는 렌더링 스레드가 있습니다 필요한 파이프라인이 제때 준비되지 않으면 게임이 멈출 수 있습니다 다른 컴파일 스레드를 추가하면 파이프라인 로딩 속도를 높일 수 있습니다. 파이프라인 컴파일이 더 빨리 완료됩니다 그러나 스레드 우선순위에 주의하지 않으면 게임은 계속해서 제시 간격을 놓칠 수 있습니다 백그라운드 완료 스레드의 우선순위를 렌더링 스레드보다 낮은 값으로 설정한 후 렌더링 스레드보다 낮은 값으로 설정된 후 끊김 현상이 사라졌습니다 이제 플레이어는 더욱 원활한 게임플레이를 즐길 수 있습니다 게임에 멀티스레드 완성 기능을 추가하는 방법은 다음과 같습니다 Metal 4 완료 API를 사용합니다 컴파일러는 Metal 4에서 폭넓게 병렬 처리될 수 있습니다 게임 아키텍처에 더 잘 맞는 방식에 따라 Grand Central Dispatch를 사용 하거나 고유한 스레드 풀을 만듭니다. 무엇이든 적절한 우선순위를 설정해야 합니다 Metal은 컴파일 작업의 우선순위를 존중합니다 Grand Central Dispatch는 멀티스레드 컴파일을 실행하는 가장 쉬운 방법입니다. 컴파일이 호출 스레드의 우선순위를 상속하려면 컴파일러가 제공하는 비동기 메서드로 디스패치 그룹을 사용할 수 있습니다. 비동기 메서드는 완료 핸들러가 있습니다 Metal은 이 메서드를 동시에 자동 실행합니다. 컴파일의 우선순위를 사용자 지정하려면 맞춤형 서비스 품질 또는 QoS 클래스를 사용해 동시 디스패치 대기열을 생성할 수 있습니다 파이프라인 사전 준비와 스트리밍의 경우 기본값으로 설정하는 것이 좋습니다. 완료 테스트를 디스패치 대기열에 제출하려면 블록에서 동기화 메서드를 호출하고 dispatch_async를 통해 대기열로 전송할 수 있습니다. 동기화 메서드는 비동기 메서드로 완료
핸들러가 없습니다 이 방식이 게임 아키텍처에 더 적합하면 고유한 스레드 풀도 생성할 수 있습니다 스레드 풀에 대한 스레드 수로 Metal 기기의 maximumConcurrentCompletion TestCount 속성을 사용합니다 이 속성을 지원하지 않는 운영 체제에서 최대 동시 실행 수가 2이므로 기본 스레드 수를 2로 설정합니다 게임의 다른 중요한 스레드 부족을 방지하기 위해 컴파일 스레드에 대해 적절한 서비스 품질 또는 QoS 클래스를 설정하는 것도 중요합니다 파이프라인 사전 준비와 스트리밍을 위해 QoS 클래스를 기본값으로 설정합니다 이제 끝입니다 이제 컴파일 작업을 스레드 풀로 보낼 수 있습니다 파이프라인 컴파일을 병렬화하고 우선순위를 지정하는 최적의 방법에 대한 자세한 정보는 Apple Developer 웹사이트의 이 문서들을 참고하세요 멀티스레드 컴파일 온디바이스 수행하면 컴파일 시간을 크게 줄일 수 있습니다 거의 0으로 줄이기 위해 개발 시점에 파이프라인을 미리 컴파일하는 것이 가장 좋습니다 파이프라인을 미리 컴파일하려면 게임은 일반적으로 종단간 워크플로를 사용합니다 워크플로는 계기 장비로 게임을 실행해 게임 내에서 사용되는 파이프라인 구성을 수집하는 것으로 시작됩니다 수집된 결과는 GPU 바이너리를 빌드하기 위해 GPU 툴체인에 제공됩니다 마지막으로 런타임에 게임은 미리 컴파일된 GPU 바이너리를 찾아 파이프라인을 빠르게 빌드합니다 Metal 4는 파이프라인 구성을 온라인에서 수집하고 출시되는 게임에서 미리 컴파일된 바이너리의 조회 과정을 더 쉽게 만들어 줍니다. Metal 4에서 파이프라인 구성을 수집하는 가장 쉬운 방법은 파이프라인 스크립트를 직렬화하는 것입니다 파이프라인 스크립트는 JSON 형식의 파일로, 기기에 작성하는 파이프라인 설명자의 텍스트 표현이 포함되어 있습니다 Metal 4에서 파이프라인 데이터 세트 직렬화기를 사용해 파이프라인 스크립트를 직렬화하기는 쉽습니다 이 객체를 컴파일러에 바인드하면 생성된 파이프라인에 대한 설명자가 자동으로 기록됩니다 그 다음 이 설명자를 파이프라인 스크립트로 직렬화할 수 있죠 파이프라인 데이터 세트 직렬화기를 생성하려면 설명자로 시작합니다. 구성을 CaptureDescriptors로 설정합니다. 이는 직렬화기에 파이프라인 설명자만 추적하도록 지시해 메모리 사용 공간을 줄입니다 직렬화기 설명자를 사용해 파이프라인 데이터 세트 직렬화기를 생성합니다. 그런 다음 컴파일러를 생성하기 위해 사용하는 컴파일러 설명자를 직렬화기에 연결합니다 컴파일러를 만든 후에는 평소처럼 파이프라인을 만드는 데 사용하면 됩니다. 직렬화기는 사용하는 파이프라인 설명자를 자동으로 기록합니다. 수집이 완료되면 serializeAsPipelines ScriptWithError를 호출해 기록된 파이프라인을 파이프라인 스크립트로 직렬화하죠 반환 값은 NSData입니다 선호하는 방법을 사용해 개발 시스템으로 다시 보낼 수 있습니다. 이 예에서는 디스크의 파일에만 작성합니다 파일 접미사를 mtl4-json으로 설정합니다 GPU 툴체인에서 예상되는 접미사입니다 파이프라인 구성을 수집한 후 다음 단계는 바이너리 빌드입니다 파이프라인 구성 스크립트와 Metal IR 라이브러리를 metal-tt에 제공합니다 Metal 아카이브에 압축된 GPU 바이너리가 출력되죠 수집된 파이프라인 스크립트를 metal-tt에 제공하기 전에 스크립트를 열고 Metal IR 라이브러리 경로를 수정해 개발 시스템의 경로와 일치시킵니다. 파이프라인 구성 스크립트 형식에 대한 자세한 내용을 보려면 이 명령을 사용해 매뉴얼 페이지를 여세요 그 다음 화면에 metal-tt 명령을 실행해 iOS에 대한 아카이브를 빌드합니다. 이제 바이너리를 미리 컴파일했으므로 게임은 런타임 시 이를 찾아야 합니다 Metal 4는 아카이브의 GPU 바이너리에서 파이프라인을 더 쉽게 만들 수 있게 합니다 기기에서 컴파일하는 데 사용하는 것과 동일한 설명자를 사용해 파이프라인 상태를 검색합니다 예를 들어 URL을 아카이브에 제공해 MTL4Archive 객체를 생성합니다 그런 다음 파이프라인 설명자를 사용해 아카이브 오브젝트에서 직접 파이프라인 상태를 쿼리하죠
아카이브 조회는 여러 가지 이유로 실패할 수 있습니다 예를 들면, 일치하는 파이프라인이 없고 OS가 호환되지 않고 GPU 아키텍처가 호환되지 않기 때문입니다 Metal 4에서는 이런 실수를 직접 처리해야 합니다 이 예는 단순히 온디바이스 컴파일로 폴백합니다 따라서 게임은 앞으로 필요한 파이프라인 상태를 유지합니다
다음은 멀티스레드 온디바이스에서 완료한 예제 게임의 CPU 타임라인입니다 완료를 미리 채택하여 파이프라인 로드 시간이 거의 0으로 줄어듭니다 사전 완료에 대해 알아보려면 Apple Developer 웹사이트의 이 문서들을 참고하세요 요약해 보자면 Metal 4는 이전보다 훨씬 빠르게 파이프라인 상태를 로드하는 뛰어난 방법을 제공 합니다. 파이프라인 특수화를 사용해 컴파일 결과를 재사용할 수 있고 멀티스레딩으로 컴파일 속도를 높일 수 있습니다 가장 낮은 파이프라인 로드 시간의 경우 간소화된 수집 및 조회 워크플로를 통해 사전 컴파일을 채택합니다 Metal 4 API로 차세대 고성능 게임 개발법을 다양하게 보여 드리게 되어 즐거웠습니다 게임의 인코딩, 리소스 관리 파이프라인 로딩의 최적화를 위해 새 Xcode를 다운로드하세요 샘플 프로젝트를 포함했으며 여러분의 여정을 지원할 자세한 문서가 준비되어 있습니다 Metal 4가 제공하는 기능을 계속 탐색하려면 이 시리즈의 다른 세션도 확인해 보시길 바랍니다 시청해 주셔서 감사합니다
-
-
0:01 - Synchronize access to a buffer within an encoder
// Synchronize access to a buffer within an encoder id<MTL4ComputeCommandEncoder> encoder = [commandBuffer computeCommandEncoder]; [encoder copyFromBuffer:src sourceOffset:0 toBuffer:buffer1 destinationOffset:0 size:64]; [encoder barrierAfterEncoderStages:MTLStageBlit beforeEncoderStages:MTLStageDispatch visibilityOptions:MTL4VisibilityOptionDevice]; [encoder setComputePipelineState:pso]; [argTable setAddress:buffer1.gpuAddress atIndex:0]; [encoder setArgumentTable:argTable]; [encoder dispatchThreads:threadsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; [encoder endEncoding];code snippet.
-
4:29 - Configure superset of color attachments
// Configure superset of color attachments MTL4RenderPassDescriptor *desc = [MTLRenderPassDescriptor renderPassDescriptor]; desc.supportColorAttachmentMapping = YES; desc.colorAttachments[0].texture = colortex0; desc.colorAttachments[1].texture = colortex1; desc.colorAttachments[2].texture = colortex2; desc.colorAttachments[3].texture = colortex3; desc.colorAttachments[4].texture = colortex4;
-
4:38 - Set color attachment map entries
// Set color attachment map entries MTLLogicalToPhysicalColorAttachmentMap* myAttachmentRemap = [MTLLogicalToPhysicalColorAttachmentMap new]; [myAttachmentRemap setPhysicalIndex:0 forLogicalIndex:0]; [myAttachmentRemap setPhysicalIndex:3 forLogicalIndex:1]; [myAttachmentRemap setPhysicalIndex:4 forLogicalIndex:2];
-
4:57 - Set a color attachment map per pipeline
// Set a color attachment map per pipeline [renderEncoder setRenderPipelineState:myPipeline]; [renderEncoder setColorAttachmentMap:myAttachmentRemap]; // Draw with myPipeline [renderEncoder setRenderPipelineState:myPipeline2]; [renderEncoder setColorAttachmentMap:myAttachmentRemap2]; // Draw with myPipeline2
-
8:03 - Encode a single render pass with 3 render encoders
// Encode a single render pass with 3 render encoders with suspend/resume options id<MTL4RenderCommandEncoder> enc0 = [cmdbuf0 renderCommandEncoderWithDescriptor:desc options:MTL4RenderEncoderOptionSuspending]; id<MTL4RenderCommandEncoder> enc1 = [cmdbuf1 renderCommandEncoderWithDescriptor:desc options:MTL4RenderEncoderOptionResuming | MTL4RenderEncoderOptionSuspending]; id<MTL4RenderCommandEncoder> enc2 = [cmdbuf2 renderCommandEncoderWithDescriptor:desc options:MTL4RenderEncoderOptionResuming]; id<MTL4CommandBuffer> cmdbufs[] = { cmdbuf0, cmdbuf1, cmdbuf2 }; [commandQueue commit:cmdbufs count:3]
-
11:48 - Synchronize drawable contents
// Synchronize drawable contents id<MTLDrawable> drawable = [metalLayer nextDrawable]; [queue waitForDrawable:drawable]; // ... encode render commands to commandBuffer ... [queue commit:&commandBuffer count:1]; [queue signalDrawable:drawable]; [drawable present];
-
13:25 - Encode a queue barrier to synchronize data
// Encode a queue barrier to synchronize data id<MTL4ComputeCommandEncoder> compute = [commandBuffer computeCommandEncoder]; [compute dispatchThreadgroups:threadGrid threadsPerThreadgroup:threadsPerThreadgroup]; [compute endEncoding]; id<MTL4RenderCommandEncoder> render = [commandBuffer renderCommandEncoderWithDescriptor:des]; [render barrierAfterQueueStages:MTLStageDispatch beforeStages:MTLStageFragment visibilityOptions:MTL4VisibilityOptionDevice]; [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:vertexStart vertexCount:vertexCount]; [render endEncoding];
-
14:57 - Create a texture view pool
// Create a texture view pool MTLResourceViewPoolDescriptor *desc = [[MTLResourceViewPoolDescriptor alloc] init]; desc.resourceCount = 500; id <MTLTextureViewPool> myTextureViewPool = [myDevice newTextureViewPoolWithDescriptor:myTextureViewPoolDescriptor error:nullptr];
-
15:07 - Set a texture view
// Set a texture view MTLResourceID myTextureView = [myTextureViewPool setTextureView:myTexture descriptor:myTextureViewDescriptor atIndex:5]; [myArgumentTable setTexture:myTextureView atIndex:0];
-
16:01 - Choose appropriate sparse page size
MTLHeapDescriptor *desc = [MTLHeapDescriptor new]; desc.type = MTLHeapTypePlacement; desc.storageMode = MTLStorageModePrivate; desc.maxCompatiblePlacementSparsePageSize = MTLSparsePageSize64; desc.size = alignedHeapSize; id<MTLHeap> heap = [device newHeapWithDescriptor:desc];
-
17:05 - Update buffer mappings
// Update buffer mappings MTL4UpdateSparseBufferMappingOperation bufferOperation; bufferOperation.mode = MTLSparseTextureMappingModeMap; bufferOperation.bufferRange.location = bufferOffsetInTiles; bufferOperation.bufferRange.length = length; bufferOperation.heapOffset = heapOffsetInTiles; [cmdQueue updateBufferMappings:myBuf heap:myHeap operations:&bufferOperation count:1];
-
20:41 - Set unspecialized configuration
// In MTL4RenderPipelineColorAttachmentDescriptor // Set unspecialized configuration pipelineDescriptor.colorAttachments[i].pixelFormat = MTLPixelFormatUnspecialized; pipelineDescriptor.colorAttachments[i].writeMask = MTLColorWriteMaskUnspecialized; pipelineDescriptor.colorAttachments[i].blendingState = MTL4BlendStateUnspecialized;
-
21:40 - Create a specialized transparent pipeline
// Create a specialized transparent pipeline // Set the previously unspecialized properties pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; pipelineDescriptor.colorAttachments[0].writeMask = MTLColorWriteMaskRed | MTLColorWriteMaskGreen | MTLColorWriteMaskBlue; pipelineDescriptor.colorAttachments[0].blendingState = MTL4BlendStateEnabled; pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; id<MTLRenderPipelineState> transparentPipeline = [compiler newRenderPipelineStateBySpecializationWithDescriptor:pipelineDescriptor pipeline:unspecializedPipeline error:&error]; // Similarly, create the specialized opaque and hologram pipelines
-
26:22 - Determine thread count
// Determine thread count NSInteger numThreads = 2; if (@available(macOS 13.3, iOS 19, visionOS 3, tvOS 19, *)) { numThreads = [device maximumConcurrentCompilationTaskCount]; }
-
26:30 - Set a proper QoS class for your compilation threads
// Create thread pool for (NSInteger i = 0; i < numThreads; ++i) { // Creating a thread with a QoS class DEFAULT pthread_attr_set_qos_class_np(&attr, QOS_CLASS_DEFAULT, 0) ; pthread_create(&threadIds[i], &attr, entryPoint, NULL); pthread_attr_destroy(&attr); }
-
28:24 - Harvest pipeline configuration scripts
// Harvest pipeline configuration scripts with the pipeline data set serializer // Create a pipeline data set serializer that only captures descriptors MTL4PipelineDataSetSerializerDescriptor *desc = [MTL4PipelineDataSetSerializerDescriptor new]; desc.configuration = MTL4PipelineDataSetSerializerConfigurationCaptureDescriptors; id<MTL4PipelineDataSetSerializer> serializer = [device newPipelineDataSetSerializerWithDescriptor:desc]; // Set the pipeline data set serializer when creating the compiler MTL4CompilerDescriptor *compilerDesc = [MTL4CompilerDescriptor new]; [compilerDesc setPipelineDataSetSerializer:serializer]; id<MTL4Compiler> compiler = [device newCompilerWithDescriptor:compilerDesc error:nil]; // Create pipelines using the compiler as usual // Serialize the descriptors as a pipeline script NSData *data = [serializer serializeAsPipelinesScriptWithError:&err]; // Write the pipeline script data to disk NSString *path = [NSString pathWithComponents:@[folder, @"pipelines.mtl4-json"]]; BOOL success = [data writeToFile:path options:NSDataWritingAtomic error:&err];
-
30:28 - Query pipeline state from MTLArchive
// Query pipeline state from MTLArchive id<MTL4Archive> archive = [device newArchiveWithURL:archiveURL error:&error]; id<MTLRenderPipelineState> pipeline = [archive newRenderPipelineStateWithDescriptor:descriptor error:&error]; if (pipeline == nil) { // handle lookup miss pipeline = [compiler newRenderPipelineStateWithDescriptor:descriptor compilerTaskOptions:nil }
-
-
- 0:00 - 서론
현대적인 게임 엔진용으로 설계된 새로운 Apple 그래픽 API인 Metal 4의 4부 시리즈 중 두 번째 시리즈입니다. Metal 4는 명령 인코딩, 리소스 관리, 파이프라인 로딩을 향상시킵니다. Metal 4는 수천 개의 셰이더로 렌더링된 기가바이트 단위의 세부적인 기하학 및 텍스처를 스트리밍하는 현재 및 미래 게임의 요구 사항을 충족하기 때문에 Apple Silicon에서 제공되는 모든 컴퓨팅 성능을 활용할 수 있습니다. MetalFX, 레이 트레이싱, 머신 러닝 통합에 대한 자세한 내용은 이 시리즈의 다른 부분도 시청해 보세요.
- 1:33 - 더 효율적으로 인코딩하기
Metal 4는 명령 인코딩을 최적화하여 GPU 효율성을 향상시키도록 설계되었습니다. 이제 대부분의 일반적인 게임 작업을 처리할 수 있는 렌더링 및 컴퓨팅이라는 두 가지 주요 인코더 클래스가 도입됩니다. Metal 4를 사용하면 인코더 수를 줄이고, 명령 메모리를 재사용하며, 여러 스레드에서 인코딩하여 인코딩 효율성을 개선할 수 있습니다.
- 8:42 - 리소스 관리 확장하기
Metal 4에는 대규모 리소스를 관리하는 데 도움이 되는 몇 가지 흥미로운 새로운 기능이 추가됩니다. 인수 테이블 및 레지던시 세트를 사용하면 리소스 바인딩을 수천 개의 리소스로 확장할 수 있습니다. Metal 4를 사용하면 그릴 수 있는 리소스를 직접 관리하고 종속성을 제어할 수 있습니다. 대기열 배리어는 대규모 리소스 종속성을 표현하는 한 가지 방법을 제공합니다. 텍스처 뷰 풀과 배치 스파스 힙은 대용량 리소스에 필요한 메모리를 관리하는 데 도움이 됩니다.
- 17:24 - 파이프라인 빠르게 로드하기
최신 게임은 복잡하고 역동적인 비주얼을 만들기 위해 수천 개의 파이프라인을 만들어야 합니다. 많은 파이프라인을 빠르게 로딩하는 것은 셰이더 컴파일 끊김을 없애고 게임 로드 시간을 줄이는 데 중요합니다. Metal 4에서 파이프라인을 빠르게 로드하려면 렌더링 파이프라인 컴파일을 재사용하고, 새로운 수준의 병렬 처리로 온디바이스에서 파이프라인을 컴파일하며, 파이프라인을 미리 컴파일하여 파이프라인 로드 시간을 거의 0으로 줄이세요.
- 31:25 - 다음 단계
Metal 4 API는 차세대 고성능 게임을 만들 수 있도록 설계되었습니다. 개발자 웹 사이트에서 문서를 확인하고, 샘플 프로젝트를 시도하며, 새로운 Xcode를 다운로드하여 시작할 수 있습니다.