Quantcast
Channel: 英特尔开发人员专区文章
Viewing all articles
Browse latest Browse all 583

Unreal Engine* 4.19 的 CPU 功能检测

$
0
0

Unreal Engine* 4.19 发布之后,许多特性针对多核处理器而优化。过去,游戏引擎在图形特性和性能方面采用控制台设计点。一般而言,多数游戏未针对处理器进行优化,这使得大量 PC 性能得不到充分发挥。英特尔与 Unreal Engine 4 的合作重点是尽快帮助使用引擎的开发人员释放游戏的潜能,以充分利用 PC 平台的所有处理器计算能力。

英特尔对 Unreal Engine* 4.19 的支持工作取得了以下成效:

  • 增加了匹配用户处理器的工作线程的数量
  • 提高了布料物理系统的吞吐量
  • 集成了对英特尔® VTune™ 放大器的支持

为了充分利用高端 CPU 的额外计算能力,英特尔开发了一款能提供详细 CPU 指标与 SynthBenchmark 性能指标的插件。CPU 功能可以使用该插件的指标来划分特性与内容。通过这种方式划分特性与内容将支持您的游戏运行于各种系统,并且不会对整体性能造成影响。

如欲下载插件,请访问 GitHub Unreal 功能检测页面。

Unreal Engine* 4.19 功能检测插件

借助功能检测插件,您可以访问兼容 C++ 和蓝图的帮助函数(面向 CPU)、渲染硬件接口 (RHI) 函数和面向 CPU/GPU 的 SynthBenchmark 性能索引。

表 1.CPU 检测函数

第三方函数蓝图函数描述
Intel_IsIntelCPU()IsIntelCPU()如果是英特尔 CPU,返回 TRUE
Intel_GetNumLogicalCores()GetNumLogicalCores()返回逻辑内核数量
Intel_GetNumPhysicalCores()GetNumPhysicalCores()返回物理内核数量
Intel_GetCoreFrequency()GetCoreFrequency()返回当前的内核频率
Intel_GetMaxBaseFrequency()GetMaxBaseFrequency()返回最大内核频率
Intel_GetCorePercMaxFrequency()GetCorePercMaxFrequency()返回正在使用的最大内核频率 %
Intel_GetFullProcessorName()GetFullProcessorName()返回长处理器名称
Intel_GetProcessorName()GetProcessorName()返回短处理器名称
Intel_GetSKU()不适用未使用

表 2.高速缓存与内存检测函数

高速缓存与 Memory 函数
第三方函数蓝图函数描述
Intel_GetUsablePhysMemoryGB()GetUsablePhysMemoryGB()返回可用的物理内存(GB)
Intel_GetComittedMemoryMB()GetComittedMemoryMB()返回占用的内存(MB)
Intel_GetAvailableMemoryMB()GetAvailableMemoryMB()返回可用的内存(MB)

表 3.渲染硬件接口 (RHI) 包装程序函数

RHI 包装程序函数
第三方函数蓝图函数描述
不适用IsRHIIntel()如果是英特尔 GPU,返回 TRUE
不适用IsRHINVIDIA()如果是 NVIDIA GPU,返回 TRUE
不适用IsRHIAMD()如果是 AMD GPU,返回 TRUE
不适用RHIVendorName()返回 GPU 的厂商名称

表 4.SynthBenchmark 包装程序函数

SynthBenchmark 包装程序函数
第三方函数蓝图函数描述
不适用ComputeCPUPerfIndex()100:一般、良好的 CPU, <100:较慢, >100:较快
不适用ComputeGPUPerfIndex()100:一般、良好的 GPU, <100:较慢, >100:较快

SynthBenchmark

使用 SythBenchmark 包装程序时需要注意,首次调用每个 ComputeCPUPerfIndex()ComputeGPUPerfIndex()都将产生少量的性能成本,同时计算性能索引。ComputeCPUPerfIndex()ComputeGPUPerfIndex()的首次和后续调用如果在运行基准性能测试时没有产生额外的开销,性能索引值将被缓存。对于游戏中依赖性能的部分,建议您在启动或加载界面的过程中调用这两个函数。

安装功能检测插件

1.从 GitHub*下载功能检测插件并打开项目文件夹。

Project folder caption

2.如果插件文件夹不在根目录中,请立即添加。

Steps to create the plugin folder

Plugin folder image

3.将功能检测插件提取至插件文件夹。

CapabilityDetect plugin folder

4.使用 .uproject 文件夹启动项目。

Steps to launch the project

5.访问主菜单中的 Edit > Plugins。加载插件窗口时,功能检测插件应安装在项目中。

Installed Capability Detect Plugin

现在,插件已安装完成,可以用它划分游戏内容与特性。下一节,我们将介绍 CPU 功能如何使用该插件划分特性。

Unreal Engine 4.19 特性划分

检测功能

为了借助平台配置划分特性,创建一个全新的 UDataAsset,并将其命名为 UPlatformConfigUPlatformConfig 将存储目标平台的特征,如物理内核数量、逻辑内核数量、可用的物理内存、处理器名称和/或 SynthBenchmark 性能索引。

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "PlatformConfig.generated.h"
/**
 * Platform Configuration Data Asset
 */
UCLASS(BlueprintType)
class CAPABILITYDETECTDEMO_API UPlatformConfig : public UDataAsset
{
       GENERATED_BODY()
public:
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float CPUPerfIndex;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       FString Name;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       bool IsIntelCPU;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       int NumPhysicalCores;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       int NumLogicalCores;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float UsablePhysMemoryGB;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float ComittedMemoryMB;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float AvailableMemoryMB;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float CacheSizeMB;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float MaxBaseFrequency;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float CoreFrequency;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       float CorePercMaxFrequency;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       FString FullProcessorName;
       UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Platform Configuration")
       FString ProcessorName;
};

接下来,我们可以使用静态功能设置名为 UPlatformTest的类,以比较 UPlatformConfig的属性与插件检测到的功能。

#include "CoreMinimal.h"
#include "PlatformTest.generated.h"
class UPlatformConfig;
/**
 * Static functions for testing capabilities.
 */
UCLASS(BlueprintType)
class CAPABILITYDETECTDEMO_API UCapabilityTest : public UObject
{
       GENERATED_BODY()
public:
       UFUNCTION(BlueprintCallable, Category = "Capabilities")
       static bool CapabilityTest(UPlatformConfig* config);
       UFUNCTION(BlueprintCallable, Category = "Capabilities")
       static UPlatformConfig* GetCapabilityLevel();
};

CapabilityTest()函数将比较 UPlatformConfig与功能检测插件检测到的特性。在本示例中,我们将检查物理内核、逻辑内核和 SynthBenchmark CPU 性能索引是否超越传输至函数的 UPlatformConfig属性。

bool UCapabilityTest::CapabilityTest(UPlatformConfig* config)
{
    // True if system capabilities exceed platform definitions
    return
        UCapabilityDetectBPLib::GetNumPhysicalCores() >= config->NumPhysicalCores
        && UCapabilityDetectBPLib::GetNumLogicalCores() >= config->NumLogicalCores
        && UCapabilityDetectBPLib::ComputeCPUPerfIndex() >= config->CPUPerfIndex;

现在,我们已经找到了一个比较功能的办法,我们可以创建另一个函数来设置与测试平台配置。我们将创建一个名为 GetCapabilityLevel()的函数,并划分 4 个等级,分别是低、中、高和超高。我们将提供一个与特性等级对应的名称,为每个被测的配置指定物理/逻辑内核和 SynthBenchmark 性能索引。最后,由于我们使用大于等于号来比较 CapabilityTest(),我们将按照从高到低的顺序进行测试,并返回结果。

UPlatformConfig* UCapabilityTest::GetCapabilityLevel()
{
       // Create Platform Definitions
       UPlatformConfig *ULTRA, *HIGH, *MEDIUM, *LOW;
       ULTRA = NewObject<UPlatformConfig>();
       HIGH = NewObject<UPlatformConfig>();
       MEDIUM = NewObject<UPlatformConfig>();
       LOW = NewObject<UPlatformConfig>();
       // Assign Properties to platform definitions.
       // LOW - 2 Physical Cores 4 Hyper-threads
       LOW->Name = TEXT("LOW");
       LOW->NumPhysicalCores = 2;
       LOW->NumLogicalCores = 4;
       LOW->CPUPerfIndex = 0.0;
       // MEDIUM - 4 Physical Cores 8 Hyper-threads
       MEDIUM->Name = TEXT("MEDIUM");
       MEDIUM->NumPhysicalCores = 4;
       MEDIUM->NumLogicalCores = 8;
       MEDIUM->CPUPerfIndex = 50.0;
       // HIGH - 6 Physical Cores 12 Hyper-threads
       HIGH->Name = TEXT("HIGH");
       HIGH->NumPhysicalCores = 6;
       HIGH->NumLogicalCores = 12;
       HIGH->CPUPerfIndex = 100.0;
       // ULTRA - 8 Physical Cores 16 Hyper-threads
       ULTRA->Name = TEXT("ULTRA");
       ULTRA->NumLogicalCores = 8;
       ULTRA->NumPhysicalCores = 16;
       ULTRA->CPUPerfIndex = 125.0;
       // Test platforms against detected capabilities.
       if (CapabilityTest(ULTRA)) {
              return ULTRA;
       }
       if (CapabilityTest(HIGH)) {
              return HIGH;
       }
       if (CapabilityTest(MEDIUM)) {
              return MEDIUM;
       }
       return LOW;
}

C++ 中的检测功能

借助 UCapabilityTest类,现在我们可以确定 CPU 特性等级。我们可以使用来自 GetCapabilityLevel()的结果来划分 C++ 或蓝图中的内容。例如,如果我们创建了一个角色,便可以划分 Tick 函数中的特性。

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
       Super::Tick(DeltaTime);
       UPlatformConfig* CapabilityLevel = UCapabilityTest::GetCapabilityLevel();
       if (CapabilityLevel->Name == TEXT("LOW"))
       {
              // Use Simple Approximation for LOW end CPU...
              // e.g. Spawn 100 CPU Particles...
       }
       else if (CapabilityLevel->Name == TEXT("MEDIUM"))
       {
              // Use Advanced Approximation for MID range CPU...
              // e.g. Spawn 200 CPU Particles
       }
       else if (CapabilityLevel->Name == TEXT("HIGH"))
       {
              // Use Simple Simulation for HIGH end CPU...
              // e.g. Spawn 300 CPU Particles
       }
      else if (CapabilityLevel->Name == TEXT("ULTRA"))
       {
              // Use Advanced Approximation for ULTRA CPU...
              // e.g. Spawn 400 CPU Particles
       }
}

蓝图中的检测功能

此外,我们可以将在角色的 Tick 函数中使用的 GetCapabilityLevel()函数应用于蓝图中,因为我们使用 UFUNCTION(BlueprintCallable) 属性对它进行了修饰。在本示例中,我们使用关卡蓝图并在 BeginPlay后调用 Get Capability Level节点。Get Capability Level节点返回的 UPlatformConfig值包含一个 Name属性。在 Switch on String 节点中,它可以用来划分您的等级特性。最后,我们只需将 CPU 特性等级的名称打印到屏幕上(图 1)。


Blueprint Capability Detect
图 1.蓝图功能检测

最后,我们介绍与功能检测插件一起封装的蓝图函数。借助该函数,您可以在蓝图中更细致地发掘平台细节。只需将检测功能节点添加至您的蓝图,然后利用游戏所需的值(图 2)。


Detect Capabilities Blueprint Node
图 2.检测功能蓝图节点

结论

随着现代 CPU 内核数量的增加,我们可以拥有更多的游戏功能。但是,相比配备高端系统的玩家,内核数量较少的玩家可能会处于劣势。为了缩小这种差距,可以使用 C++ 和蓝图划分特性。如前所示,划分特性将实现最大的 CPU 利用率,同时通过一系列平台配置帮助玩家维持固定的帧速率。


Viewing all articles
Browse latest Browse all 583

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>