Version: 2023.2
언어: 한국어
컬링그룹 API
FrameTimingManager

다이내믹 해상도

다이내믹 해상도는 개별 렌더 타겟을 동적으로 스케일링하여 GPU의 부하를 줄여주는 카메라 설정입니다. 애플리케이션의 프레임 속도가 감소하는 경우에는 일관된 프레임 속도를 유지하기 위해 점진적으로 해상도를 스케일다운할 수 있습니다. 성능 데이터가 애플리케이션의 GPU 바운드로 인해 프레임 속도가 떨어진다고 암시하는 경우 Unity는 이 스케일링 방식을 트리거합니다. 애플리케이션의 특정 GPU 과부하 섹션을 선점한 후 스크립트를 통해 스케일링을 제어하는 방식으로 스케일링을 수동으로 트리거할 수도 있습니다. 점진적으로 스케일링하면 다이내믹 해상도는 거의 눈에 띄지 않습니다.

렌더 파이프라인 호환성

Dynamic resolution support depends on which render pipeline your project uses.

기능 빌트인 렌더 파이프라인 유니버설 렌더 파이프라인(URP) 고해상도 렌더 파이프라인(HDRP)
다이내믹 해상도 지원(1) 지원(1) 지원(2)

참고:

  1. The Built-in Render Pipeline, and the Universal Render Pipeline (URP) both support dynamic resolution as described in this document.
  2. The High Definition Render Pipeline (HDRP) supports dynamic resolution, but you enable and use it in a different way. For information on dynamic resolution in HDRP, see Dynamic resoluton in HDRP.

지원되는 플랫폼

Unity supports dynamic resolution on iOS, macOS and tvOS (Metal only), Android (Vulkan only), Windows Standalone (DirectX 12 only), and UWP (DirectX 12 only).

렌더 타겟에 대한 영향

다이내믹 해상도를 사용하는 경우 Unity는 렌더 타겟을 재할당하지 않습니다. 개념적으로는 Unity가 렌더 타겟을 스케일링하지만, 실제로 Unity는 앨리어싱을 사용합니다. 또한 스케일다운된 렌더 타겟은 원본 렌더 타겟의 작은 부분만 사용합니다. Unity가 전체 해상도로 렌더 타겟을 할당하면, 다이내믹 해상도 시스템이 스케일다운을 통해 다시 백업합니다. 이때 새 타겟을 재할당하지 않고 원본 타겟의 일부를 사용합니다.

렌더 타겟 스케일링

다이내믹 해상도를 사용하는 경우 렌더 타겟에 DynamicallyScalable 플래그가 생깁니다. 이 플래그를 설정하면 Unity가 다이내믹 해상도 프로세스의 일부로 이 렌더 텍스처를 스케일링해야 하는지 여부를 지정할 수 있습니다. 또한 카메라에 생기는 allowDynamicResolution 플래그를 사용하여 다이내믹 해상도를 설정하면, 덜 복잡한 씬에 다이내믹 해상도를 적용하는 경우에 렌더 타겟을 오버라이드할 필요가 없습니다.

MRT 버퍼

카메라에서 Allow Dynamic Resolution 을 활성화하면 Unity는 카메라의 모든 타겟을 스케일링합니다.

스케일링 제어

ScalableBufferManager를 통해 스케일을 제어할 수 있습니다. ScalableBufferManager를 이용하면 다이내믹 해상도 시스템에서 스케일링하도록 표시한 모든 렌더 타겟의 동적 너비와 높이 스케일을 제어할 수 있습니다.

예를 들어 애플리케이션이 원하는 프레임 속도로 실행되지만, 일부 환경에서 증가된 파티클, 포스트 효과, 화면 복잡도 등으로 인해 GPU 성능이 저하된다고 가정하겠습니다. Unity FrameTimingManager를 이용하면 CPU 또는 GPU 성능이 저하되는 순간을 탐지할 수 있습니다. 따라서 FrameTimingManager를 사용하여 새로운 너비와 높이 스케일을 계산하여 프레임 속도를 원하는 범위 내에서 유지하고 해당 값을 스케일다운하여 즉시 또는 일련의 프레임 구간에서 점진적으로 성능을 안정적으로 유지할 수 있습니다. 화면 복잡도가 감소하고 GPU가 일관되게 동작하면 GPU가 처리할 수 있다고 계산한 원래 값으로 너비와 높이 스케일을 다시 높일 수 있습니다.

예제

This example script demonstrates basic use of the API. Add it to a Camera in your Scene, and check Allow Dynamic Resolution in the Camera settings. You also need to open the Player settings (menu: Edit > Project Settings, then select the Player category) and check the Enable Frame Timing Stats checkbox. For more information about the functionality behind the Enable Frame Timing Stats property, see FrameTimingManager.

마우스 오른쪽 버튼을 클릭하거나 화면을 한 손가락으로 탭하면 높이 및 너비 해상도가 scaleWidthIncrementscaleHeightIncrement 변수의 양만큼 각각 감소합니다. 두 손가락으로 탭하면 동일한 인크리먼트만큼 해상도가 증가합니다.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DynamicResolutionTest : MonoBehaviour
{
    public Text screenText;

    FrameTiming[] frameTimings = new FrameTiming[3];

    public float maxResolutionWidthScale = 1.0f;
    public float maxResolutionHeightScale = 1.0f;
    public float minResolutionWidthScale = 0.5f;
    public float minResolutionHeightScale = 0.5f;
    public float scaleWidthIncrement = 0.1f;
    public float scaleHeightIncrement = 0.1f;

    float m_widthScale = 1.0f;
    float m_heightScale = 1.0f;

    // Variables for dynamic resolution algorithm that persist across frames
    uint m_frameCount = 0;

    const uint kNumFrameTimings = 2;

    double m_gpuFrameTime;
    double m_cpuFrameTime;

    // Use this for initialization
    void Start()
    {
        int rezWidth = (int)Mathf.Ceil(ScalableBufferManager.widthScaleFactor * Screen.currentResolution.width);
        int rezHeight = (int)Mathf.Ceil(ScalableBufferManager.heightScaleFactor * Screen.currentResolution.height);
        screenText.text = string.Format("Scale: {0:F3}x{1:F3}\nResolution: {2}x{3}\n",
            m_widthScale,
            m_heightScale,
            rezWidth,
            rezHeight);
    }

    // Update is called once per frame
    void Update()
    {
        float oldWidthScale = m_widthScale;
        float oldHeightScale = m_heightScale;

        // One finger lowers the resolution
        if (Input.GetButtonDown("Fire1"))
        {
            m_heightScale = Mathf.Max(minResolutionHeightScale, m_heightScale - scaleHeightIncrement);
            m_widthScale = Mathf.Max(minResolutionWidthScale, m_widthScale - scaleWidthIncrement);
        }

        // Two fingers raises the resolution
        if (Input.GetButtonDown("Fire2"))
        {
            m_heightScale = Mathf.Min(maxResolutionHeightScale, m_heightScale + scaleHeightIncrement);
            m_widthScale = Mathf.Min(maxResolutionWidthScale, m_widthScale + scaleWidthIncrement);
        }

        if (m_widthScale != oldWidthScale || m_heightScale != oldHeightScale)
        {
            ScalableBufferManager.ResizeBuffers(m_widthScale, m_heightScale);
        }
        DetermineResolution();
        int rezWidth = (int)Mathf.Ceil(ScalableBufferManager.widthScaleFactor * Screen.currentResolution.width);
        int rezHeight = (int)Mathf.Ceil(ScalableBufferManager.heightScaleFactor * Screen.currentResolution.height);
        screenText.text = string.Format("Scale: {0:F3}x{1:F3}\nResolution: {2}x{3}\nScaleFactor: {4:F3}x{5:F3}\nGPU: {6:F3} CPU: {7:F3}",
            m_widthScale,
            m_heightScale,
            rezWidth,
            rezHeight,
            ScalableBufferManager.widthScaleFactor,
            ScalableBufferManager.heightScaleFactor,
            m_gpuFrameTime,
            m_cpuFrameTime);
    }

    // Estimate the next frame time and update the resolution scale if necessary.
    private void DetermineResolution()
    {
        ++m_frameCount;
        if (m_frameCount <= kNumFrameTimings)
        {
            return;
        }
        FrameTimingManager.CaptureFrameTimings();
        FrameTimingManager.GetLatestTimings(kNumFrameTimings, frameTimings);
        if (frameTimings.Length < kNumFrameTimings)
        {
            Debug.LogFormat("Skipping frame {0}, didn't get enough frame timings.",
                m_frameCount);

            return;
        }

        m_gpuFrameTime = (double)frameTimings[0].gpuFrameTime;
        m_cpuFrameTime = (double)frameTimings[0].cpuFrameTime;
    }
}

참고 항목


  • 2018–09–20 페이지 게시됨

  • Unity 2017.4에서 다이내믹 해상도에 대한 설명 추가됨

  • 2019.1에서 macOS (Metal만 해당), Windows 스탠드얼론 및 UWP(DirectX 12에만 해당)의 다이내믹 해상도 지원 추가됨

컬링그룹 API
FrameTimingManager
Copyright © 2023 Unity Technologies
优美缔软件(上海)有限公司 版权所有
"Unity"、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其附属机构在美国及其他地区的商标或注册商标。其他名称或品牌是其各自所有者的商标。
公安部备案号:
31010902002961