Virtual Texture 페이지 체류율 분석으로 고해상도 텍스처 우선순위 조정하기

Unreal Engine 5의 Virtual Texture 페이지 체류율, 가시성, 요청 지연 시간, 메모리 비용을 함께 분석해 고해상도 텍스처 우선순위를 정하고 VT 풀 고갈과 화질 저하를 줄이는 실전 방법을 설명합니다. 프로파일링 기준과 집계 SQL 예제도 제공합니다.

✓ 복사 완료!
챕터머티리얼 & 텍스처
난이도중급
상태● 검토 완료
대상 엔진
Engine Agnostic
최종 업데이트
Virtual Texture 페이지 체류율 분석으로 고해상도 텍스처 우선순위 조정하기

핵심 요약

Virtual Texture 페이지의 체류율은 해당 페이지가 실제 화면에 보이는 동안 메모리에 상주한 비율로 정의하는 것이 유용합니다. 체류율만으로 우선순위를 정하지 말고 가시 시간, 화면 점유 면적, 요청 지연 시간, 아트 중요도, 메모리 비용을 함께 계산해야 합니다. 이렇게 하면 자주 보이고 오래 필요한 고해상도 텍스처는 우선 보호하고 일시적으로만 보이는 페이지는 낮은 우선순위로 조정할 수 있습니다.

이 글은 Unreal Engine 5의 Virtual Texture Streaming을 중심으로 설명합니다. Runtime Virtual Texture는 캐시 갱신 방식과 사용 목적이 다르므로 동일한 지표로 섞어 분석하지 않는 것이 좋습니다.

Virtual Texture 페이지 체류율은 무엇을 의미하는가?

일반적인 텍스처 스트리밍에서는 텍스처 단위로 메모리 상주 여부를 확인하는 경우가 많습니다. Virtual Texture는 큰 텍스처를 작은 타일 페이지로 나누고 필요한 페이지와 밉 레벨만 스트리밍하므로 텍스처 전체가 아니라 다음 단위로 분석해야 합니다.

  • asset_id: Virtual Texture 에셋 식별자
  • mip: 밉 레벨. 일반적으로 0이 가장 높은 해상도입니다.
  • tile_x, tile_y: 해당 밉 레벨의 타일 좌표
  • page_id: asset_id + mip + tile_x + tile_y 조합

이 글에서 체류율은 다음처럼 정의합니다.

Ri=DiWiR_i = \frac{D_i}{W_i}
  • W_i: 페이지 i가 화면에 보일 가능성이 있었던 전체 시간
  • D_i: 그중 페이지가 실제로 메모리에 상주한 시간
  • R_i: 가시 상태에서의 페이지 체류율

페이지가 메모리에 남아 있지만 카메라 뒤에 있거나 다른 머티리얼 샘플에 사용되지 않았다면 D_i에 포함하지 않습니다. 단순한 캐시 상주 시간과 가시 상태의 체류 시간을 구분해야 우선순위 분석이 실제 화질 문제와 연결됩니다.

페이지 체류율과 요청 지연 시간은 어떻게 다른가?

두 지표는 서로 다른 문제를 설명합니다. 체류율은 페이지를 얼마나 안정적으로 유지했는지 보여주고 요청 지연 시간은 필요한 페이지가 화면에 나타나기까지 얼마나 늦었는지를 보여줍니다.

지표계산 방법해석조정 방향
가시 시간 W화면에 보일 수 있었던 시간노출량오래 노출되는 에셋 확인
체류 시간 D가시 상태에서 메모리에 있었던 시간실제 디테일 유지 시간낮으면 캐시 경쟁 조사
체류율 RD / W가시 중 상주 비율낮은 페이지의 우선순위 검토
요청 지연 Lresident_at - request_at페이지 도착 속도IO, 압축, 풀 용량 점검
미스율 M요청 중 늦게 도착한 요청 비율화질 저하 가능성우선순위와 스트리밍 예산 조정
메모리 비용 C페이지 크기와 밉 수 기반 추정캐시 점유 비용비용 대비 효과 비교

예를 들어 체류율은 높지만 요청 지연 시간이 길다면 페이지가 한 번 로드된 뒤에는 잘 유지되고 있다는 뜻입니다. 이 경우 우선순위를 올리기보다 디스크 IO, 압축 해제, 비동기 업로드, 피드백 버퍼 읽기 지연을 먼저 확인해야 합니다.

반대로 요청 지연 시간은 짧지만 체류율이 낮다면 Virtual Texture Pool에서 페이지가 빠르게 밀려나는 상황일 수 있습니다. 이때는 고해상도 밉을 무조건 추가하기보다 페이지 경쟁과 화면 점유 면적을 함께 분석해야 합니다.

어떤 데이터를 수집해야 하는가?

Unreal Engine 5의 Virtual Texture Streaming은 머티리얼 샘플링 결과와 피드백 패스를 바탕으로 필요한 페이지를 요청합니다. GPU 피드백은 비동기적으로 CPU에 전달될 수 있으므로 이벤트를 기록할 때 프레임 번호와 타임스탬프를 함께 보관해야 합니다.

권장 이벤트 필드는 다음과 같습니다.

필드용도
build_id빌드와 설정별 결과 비교
map_name레벨별 편차 확인
camera_route특정 플레이 경로 재현
frame_idGPU 피드백 지연 보정
asset_id텍스처 에셋별 집계
mip, tile_x, tile_y실제 페이지 단위 분석
request_at페이지 요청 시점
resident_at메모리 상주 시점
evicted_at캐시에서 제거된 시점
visible_ms화면에 보인 시간
projected_area화면 점유 면적
miss_flag목표 시간 안에 준비되지 않았는지 여부
quality_tier콘솔, PC, 고성능 PC 등 설정 구분

매 프레임 모든 페이지를 기록하면 텔레메트리 비용이 커질 수 있습니다. 개발 빌드에서는 이벤트 기반 기록을 사용하고 가시 시간과 화면 점유 면적은 5~10Hz로 샘플링하는 방법이 실용적입니다. 최종 검증에서는 대표적인 카메라 경로와 품질 단계별로 같은 장면을 반복 측정해야 합니다.

Virtual Texture 페이지 요청, 상주, 이탈 시간을 보여주는 분석 대시보드 예시

고해상도 텍스처 우선순위를 어떻게 계산할까?

페이지 우선순위는 엔진에 기본 제공되는 하나의 표준 공식이 아니라 프로젝트의 스트리밍 정책을 위한 분석 점수로 설계할 수 있습니다. 다음은 고해상도 페이지를 평가하는 예시입니다.

Si=Wi⋅Ri⋅Ai⋅QiCi⋅(1+λMi)S_i = \frac{W_i \cdot R_i \cdot A_i \cdot Q_i}{C_i} \cdot (1 + \lambda M_i)

각 변수는 0과 1 사이로 정규화합니다.

  • W_i: 전체 측정 구간 대비 가시 시간
  • R_i: 가시 상태에서의 체류율
  • A_i: 화면 점유 면적 또는 projected screen size
  • Q_i: 주인공, 무기, UI 근접 오브젝트 등 아트 중요도
  • C_i: 페이지의 메모리 비용
  • M_i: 목표 지연 시간을 초과한 요청 비율
  • λ: 미스율을 얼마나 강하게 반영할지 결정하는 가중치

Q_i는 자동으로 정하기 어렵기 때문에 아트 디렉션과 기술 아트 기준을 함께 반영합니다. 예를 들어 주인공 얼굴과 무기는 높은 값을 주고 배경의 작은 장식물은 낮은 값을 줄 수 있습니다.

다만 점수가 높다고 항상 mip 0을 유지해야 하는 것은 아닙니다. 화면 점유 면적이 작다면 고해상도 페이지를 로드해도 플레이어가 차이를 인식하지 못할 수 있습니다. 따라서 에셋 단위가 아니라 asset_id + mip 단위로 점수를 집계하고 실제 화면 크기에서 시각적 이득이 있는지 확인해야 합니다.

체류율 데이터를 어떤 방식으로 집계할까?

다음 SQL은 분석 테이블 vt_page_events를 기준으로 페이지별 가시 시간, 가시 상태 상주 시간, 요청 지연 시간, 미스율을 집계하는 예시입니다. 실제 컬럼명과 SQL 엔진에 맞게 수정해야 합니다.

WITH page_summary AS (
  SELECT
    asset_id,
    mip,
    tile_x,
    tile_y,
    SUM(visible_ms) AS visible_ms,
    SUM(CASE WHEN resident = TRUE THEN visible_ms ELSE 0 END) AS resident_visible_ms,
    AVG(request_to_resident_ms) AS avg_latency_ms,
    AVG(CASE WHEN miss_flag = TRUE THEN 1.0 ELSE 0.0 END) AS miss_rate,
    AVG(projected_area) AS avg_projected_area
  FROM vt_page_events
  WHERE build_id = :build_id
  GROUP BY asset_id, mip, tile_x, tile_y
)
SELECT
  asset_id,
  mip,
  tile_x,
  tile_y,
  visible_ms,
  resident_visible_ms,
  resident_visible_ms / NULLIF(visible_ms, 0) AS residency_ratio,
  avg_latency_ms,
  miss_rate,
  avg_projected_area
FROM page_summary
ORDER BY residency_ratio ASC, miss_rate DESC;

페이지 이벤트가 구간 단위로 기록된다면 페이지가 실제로 보인 구간과 상주 구간의 교집합을 계산해야 합니다. 페이지가 화면에 보이기 전에 미리 로드된 시간은 체류 시간에 포함하지 않는 것이 핵심입니다.

GPU 피드백 결과가 한 프레임 이상 늦게 도착하는 경우에는 request_at을 피드백 수신 시간이 아니라 원래 샘플링된 frame_id에 매핑해야 합니다. 그렇지 않으면 모든 페이지의 요청 지연 시간이 실제보다 길게 계산될 수 있습니다.

우선순위 조정은 어떤 순서로 진행할까?

1단계: 대표 카메라 경로를 고정한다

테스트 경로가 달라지면 페이지 집합도 달라집니다. 주인공 이동, 전투, 컷신, 실내외 전환, 빠른 카메라 회전이 포함된 경로를 정하고 동일한 빌드와 품질 설정으로 반복 실행합니다.

측정 범위에는 다음 조건을 포함하는 것이 좋습니다.

  • 평균적인 플레이 경로
  • 가장 가까운 카메라 거리
  • 가장 빠른 회전 또는 이동 구간
  • 텍스처가 많이 겹치는 전투 구간
  • 레벨 스트리밍과 동시에 발생하는 구간

2단계: 미스율과 체류율을 함께 분류한다

페이지를 다음 네 그룹으로 나누면 조정 방향을 빠르게 결정할 수 있습니다.

분류체류율미스율우선 조치
핵심 고해상도 페이지높음높음우선순위 상승 또는 선행 요청
안정적인 페이지높음낮음현재 정책 유지
도착은 빠르지만 자주 교체되는 페이지낮음낮음~중간Pool 경쟁과 밉 전환 확인
일시적 노출 페이지낮음높음해상도 제한, 선행 로드 여부 재검토

높은 미스율을 무조건 우선순위 상승으로 해결하면 메모리 사용량이 빠르게 증가할 수 있습니다. 먼저 페이지가 왜 필요한지 확인하고 화면 점유 면적이 작은 경우에는 높은 밉 레벨을 제한하는 편이 더 효율적입니다.

3단계: 우선순위 정책을 적용한다

실제 적용 방법은 프로젝트의 엔진 버전과 스트리밍 코드에 따라 달라집니다. 일반적으로 다음 순서로 조정합니다.

  1. 주인공과 근접 카메라 에셋의 Q_i를 높인다.
  2. 높은 W_i, A_i, M_i를 가진 mip 0~2 페이지를 우선 보호한다.
  3. 화면 점유 면적이 작은 배경 에셋은 최대 밉 또는 LOD Bias를 제한한다.
  4. Virtual Texture Pool 부족이 원인일 때만 r.VT.PoolSize와 플랫폼별 메모리 예산을 검토한다.
  5. 우선순위 변경 후 동일한 카메라 경로에서 체류율, 미스율, GPU 시간, 메모리 사용량을 재측정한다.

r.VT.PoolSize를 크게 만드는 것은 모든 페이지 문제의 해결책이 아닙니다. 풀을 늘리면 메모리 압박과 다른 렌더링 리소스의 예산 감소가 발생할 수 있으므로 플랫폼별 상한을 정해 검증해야 합니다.

Streaming Virtual Texture와 Runtime Virtual Texture를 어떻게 구분할까?

두 시스템을 같은 대시보드에서 집계하면 원인 분석이 어려워집니다.

구분Streaming Virtual TextureRuntime Virtual Texture
주요 목적큰 소스 텍스처를 필요한 페이지와 밉만 스트리밍월드에 머티리얼 결과를 캐시하고 재사용
주요 사용 사례캐릭터, 소품, 환경 텍스처랜드스케이프, 지형 블렌딩, 런타임 투영
핵심 문제페이지 요청 지연과 Pool 경쟁캐시 갱신, 볼륨 범위, 업데이트 비용
분석 단위에셋, 밉, 타일 페이지볼륨, 캐시 영역, 갱신 주기

RVT 페이지의 체류율이 낮다는 이유만으로 Streaming Virtual Texture의 우선순위를 조정하면 잘못된 결론에 도달할 수 있습니다. 데이터에 virtual_texture_type 필드를 넣고 최소한 SVT와 RVT를 분리해 집계하세요.

잘못된 분석을 피하려면 무엇을 확인해야 하는가?

첫째는 프리패치와 실제 가시성을 구분하는 것입니다. 카메라가 곧 바라볼 영역을 미리 로드하는 시스템에서는 페이지가 오래 상주해도 현재 화면에는 보이지 않을 수 있습니다.

둘째는 밉 전환을 페이지 미스로 오해하지 않는 것입니다. 카메라 거리나 projected screen size가 바뀌면서 낮은 해상도 밉으로 전환되는 것은 정상 동작일 수 있습니다. 목표 해상도 밉이 필요한 상황에서 정해진 시간 안에 도착하지 못한 경우만 미스로 분류해야 합니다.

셋째는 페이지 크기만으로 비용을 판단하지 않는 것입니다. 같은 크기의 타일이라도 압축률, 밉 수, 포맷, 플랫폼 메모리 예산에 따라 실제 비용이 달라질 수 있습니다.

넷째는 평균값만 보지 않는 것입니다. 평균 체류율이 좋아도 빠른 카메라 회전이나 특정 컷신에서 p95 요청 지연 시간이 급증할 수 있습니다. 최소한 평균, p90 또는 p95, 최악 구간을 함께 비교하세요.

성공 여부는 어떤 기준으로 검증할까?

우선순위 조정은 화질 개선만으로 평가하면 안 됩니다. 다음 지표를 변경 전후로 비교해야 합니다.

검증 항목확인할 질문
체류율핵심 고해상도 페이지가 더 오래 유지되는가?
미스율화면에 보이는 순간 저해상도 fallback이 줄었는가?
요청 지연 p95빠른 이동과 회전에서 지연이 악화되지 않았는가?
VT Pool 사용량메모리 예산 상한을 넘지 않는가?
GPU 시간피드백과 페이지 처리 비용이 증가하지 않았는가?
비핵심 에셋 품질배경과 소품이 과도하게 희생되지 않았는가?

가능하면 동일한 카메라 경로를 기준으로 A/B 빌드를 비교합니다. 한쪽에는 기존 우선순위 정책을 적용하고 다른 쪽에는 체류율 기반 정책을 적용한 뒤 성능과 시각 품질을 함께 평가합니다.

자주 묻는 질문 (FAQ)

페이지 체류율이 낮으면 무조건 고해상도 우선순위를 높여야 하나요?

아닙니다. 체류율이 낮은 원인이 Pool 경쟁인지 화면 점유 면적이 작은 정상적인 밉 전환인지 먼저 확인해야 합니다. 핵심 에셋이고 미스율과 projected screen size가 모두 높을 때 우선순위 상승을 검토합니다.

텍스처 에셋 단위와 페이지 단위 중 무엇을 기준으로 삼아야 하나요?

최종 결정은 페이지 단위가 적합합니다. 하나의 텍스처 안에서도 주인공 얼굴 주변 페이지와 배경 페이지의 노출량이 다르기 때문입니다. 다만 운영 대시보드에서는 에셋 단위로 요약하고 원인 분석은 asset_id + mip + tile 단위로 내려가는 방식이 효율적입니다.

Virtual Texture Pool 크기를 늘리면 문제가 해결되나요?

일부 Pool 부족 문제는 완화할 수 있지만 근본 해결책은 아닙니다. 메모리 예산이 허용되는지 확인한 뒤 페이지 우선순위, 밉 제한, 요청 지연, 페이지 경쟁을 함께 조정해야 합니다.

정리

Virtual Texture 페이지의 우선순위는 단순히 고해상도 에셋인지 여부로 결정하기 어렵습니다. 가시 시간 × 체류율 × 화면 점유 면적 × 아트 중요도를 메모리 비용과 미스율에 연결해 페이지별 점수를 만들면 실제 플레이에서 체감되는 디테일을 중심으로 스트리밍 예산을 배분할 수 있습니다.

핵심은 SVT와 RVT를 분리하고 asset_id + mip + tile 단위로 데이터를 수집하는 것입니다. 이후 동일한 카메라 경로에서 p95 지연 시간, 미스율, 체류율, Pool 사용량을 함께 검증하면 고해상도 텍스처 우선순위가 화질과 성능 중 어느 쪽에 어떤 영향을 주는지 재현 가능하게 판단할 수 있습니다.