使用 AMD FreeSync™ Premium Pro HDR 代码示例

最初发布于:
Ihor Szlachtycz's avatar
Ihor Szlachtycz

现在我们已经了解了 FreeSync HDR、它提供的功能以及需要修改才能利用 FreeSync HDR 的所有后期处理通道,我们可以看看如何使用所有下一代图形 API 来启用 FreeSync HDR。

我们将使用一个示例来演示如何实现这一点。您可以在 GitHub 上找到本教程中使用的示例。

在 GitHub 上查看 FreeSync 示例

在显示器上启用 FreeSync HDR

要使显示器上的 FreeSync HDR 生效,您需要执行以下操作:

  • 将显示器的固件更新到最新版本
  • 前往 AMD Radeon Settings -> Display -> AMD FreeSync 并确保已启用 – FreeSync 框中应有一个白色圆圈。
  • 最后,您需要在显示器的设置中启用 FreeSync HDR。这通常通过显示器的菜单按钮和显示设置选项来访问,并启用 FreeSync Premium(或 HDR)。

完成上述操作后,您的显示器上应该已正确启用 FreeSync HDR。

FreeSync HDR 和 DirectX® 12

我们将通过我们发布的 FreeSync HDR DX12 代码示例来演示如何将 FreeSync HDR 集成到游戏引擎中,该示例可在 GitHub 此处找到。DX12 中的 FreeSync HDR API 通过 AGS(AMD GPU Services 库)公开,该库可在 GitHub 此处找到。

首先,应用程序必须像在 Device.cpp 中看到的那样初始化 AGS。

// Create AGS context
AGSReturnCode result = agsInit(&m_agsContext, NULL, &m_agsGPUInfo);

m_agsContext 存储 AGS 所需的全局数据,而 m_agsGPUInfo 是指向计算机上每台已连接 GPU 的元数据数组的指针。m_agsGPUInfo 数组中的每个实例都存储指向连接到该 GPU 的所有显示器的元数据指针。这意味着应用程序需要选择要显示的 GPU,找到我们正在渲染的显示器,并检查它是否支持 FreeSync HDR。

这可以在 Freesync2.cpp 中看到。

bool fs2EnumerateDisplayModes(std::vector *pModes)
{
// ...
const int numDevices = m_pGPUInfo->numDevices;
const AGSDeviceInfo* devices = m_pGPUInfo->devices;
int numDisplays = devices[0].numDisplays;
// Find which display the app window is rendering to and store it in bestDisplayIndex
// and check for FS2 support
if (devices[0].displays[bestDisplayIndex].displayFlags & AGSDisplayFlags::AGS_DISPLAYFLAG_FREESYNC_2)
{
pModes->push_back(DISPLAYMODE_FS2_Gamma22);
pModes->push_back(DISPLAYMODE_FS2_SCRGB);
}
// ...
}

在上面的示例中,我们假设第一块 GPU 是主 GPU,但实际游戏应该有逻辑允许玩家选择他们想要渲染的 GPU。displays 数组中存储的数据是我们之前博客文章中讨论过的查询到的显示器数据。它包含显示器的原生色彩空间主色调、最小/最大亮度等。您可以在 amd_ags.h 中查看结构的完整内容。

我们找到应用程序正在呈现的显示器,然后检查它是否设置了 FreeSync HDR 显示标志。

在确认显示器支持 FreeSync HDR 后,使用标准的 DX12 代码创建交换链。将颜色格式初始化为我们想要支持的所需 FreeSync HDR 颜色格式非常重要。对于 DisplayNative 或 Gamma22,这将是 DXGI_FORMAT_R10G10B10A2_UNORM,对于 scRGB,这将是 DXGI_FORMAT_R16G16B16A16_FLOAT。应用程序还需要通过 Windows® API 将其窗口设置为独占全屏模式。这可以通过创建具有无边框全屏标志的窗口,并使其大小和分辨率与显示器匹配来实现。

接下来,我们需要填充一个 AGSDisplaySettings 结构,我们将其发送给驱动程序以配置我们想要渲染的 FreeSync HDR 模式,如 Freesync2.cpp 中所示。

s_AGSDisplayInfo = m_pGPUInfo->devices[0].displays[s_displayIndex];
switch (displayMode)
{
case DISPLAYMODE_FS2_Gamma22:
{
agsDisplaySettings.mode = AGSDisplaySettings::Mode::Mode_Freesync2_Gamma22;
agsDisplaySettings.flags = disableLocalDimming;
break;
}
case DISPLAYMODE_FS2_SCRGB:
{
agsDisplaySettings.mode = AGSDisplaySettings::Mode::Mode_Freesync2_scRGB;
agsDisplaySettings.flags = disableLocalDimming;
break;
}
// ...
}
agsDisplaySettings.chromaticityRedX = s_AGSDisplayInfo.chromaticityRedX;
agsDisplaySettings.chromaticityRedY = s_AGSDisplayInfo.chromaticityRedY;
agsDisplaySettings.chromaticityGreenX = s_AGSDisplayInfo.chromaticityGreenX;
agsDisplaySettings.chromaticityGreenY = s_AGSDisplayInfo.chromaticityGreenY;
agsDisplaySettings.chromaticityBlueX = s_AGSDisplayInfo.chromaticityBlueX;
agsDisplaySettings.chromaticityBlueY = s_AGSDisplayInfo.chromaticityBlueY;
agsDisplaySettings.chromaticityWhitePointX = s_AGSDisplayInfo.chromaticityWhitePointX;
agsDisplaySettings.chromaticityWhitePointY = s_AGSDisplayInfo.chromaticityWhitePointY;
agsDisplaySettings.minLuminance = s_AGSDisplayInfo.minLuminance;
if (disableLocalDimming)
s_AGSDisplayInfo.maxLuminance = s_AGSDisplayInfo.avgLuminance;
agsDisplaySettings.maxLuminance = s_AGSDisplayInfo.maxLuminance;

最后,我们调用函数来设置显示模式。

AGSReturnCode rc = agsSetDisplayMode(s_pAGSContext, 0, s_displayIndex, &agsDisplaySettings);
assert(rc == AGS_SUCCESS);

在上面的代码中,我们填充了一个 AGSDisplaySettings 结构,并通过 agsSetDisplayMode 将其发送给驱动程序。您会注意到大多数值都从 m_AGSDisplayInfo(显示器的元数据)复制而来,但有几个值需要我们计算。根据游戏是否启用局部调光,maxLuminanceflags 的值需要设置得不同。

在向 AGS 和游戏色调映射器提供显示器的最大亮度时,如果启用了局部调光,我们需要提供 m_AGSDisplayInfo.maxLuminance 的值,否则我们提供 m_AGSDisplayInfo.avgLuminance 的值。正如在关于色调映射的帖子中所解释的,是否启用或禁用局部调光取决于游戏。FreeSync HDR 提供了这样做的选项,并为这两种情况提供了正确的最大亮度值。游戏还应向色域映射器提供显示器的色度值,以便映射器知道目标色域是什么。

设置显示设置后,我们的游戏就配置为在 DX12 的 FreeSync HDR 模式下进行渲染了!在实际游戏中,玩家通常可以选择更改游戏正在渲染的显示器,或是否处于 FreeSync HDR 模式。当发生此类更改时,将需要重新创建交换链,并且需要再次设置显示设置。游戏还需要重新馈送显示器的元数据,但初始化 AGS 和获取 GPU 元数据只在游戏初始化期间进行一次。

最后一步是向色调映射器提供显示器亮度数据,向色域映射器提供显示器的色度值,并以正确的 FreeSync HDR 格式对最终帧缓冲区进行编码。色调和色域映射器是游戏特定的,因此我们无法详细介绍如何集成它们,因为它在每个引擎中都不同。但是,我们将在下面的 FreeSync HDR 显示格式部分的 HLSL 代码 中介绍如何编码最终帧缓冲区的颜色。

FreeSync HDR 和 Vulkan

我们将通过我们发布的 FreeSync HDR Vulkan 代码示例来演示如何将 FreeSync HDR 集成到游戏引擎中,该示例可在 GitHub 此处找到。Vulkan 中的 FreeSync HDR API 通过从 Vulkan 内部查询的扩展公开。

在设置 Vulkan 并开始创建我们的实例后,我们必须查询以检查文件 ExtFreeSync2.cpp 中的以下实例扩展是否受支持。

std::vector required_extension_names = {
VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME
};

此扩展增加了实例级别的支持,用于从显示器查询 HDR 元数据。

之后,我们使用标准 Vulkan 代码和请求的扩展创建我们的实例,并查询其相应的函数。

然后,我们创建表面和设备,如 Device.cpp 中所示,引用 ExtFreeSync2.cpp 中的以下扩展。

std::vector required_extension_names = {
VK_EXT_HDR_METADATA_EXTENSION_NAME,
VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME,
VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME
};

这些 FreeSync HDR 扩展如下:

  • VK_EXT_HDR_METADATA_EXTENSION_NAME – 允许我们查询和设置交换链的 HDR 显示格式。
  • VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME – 允许我们查询和设置表面上的 FreeSync HDR 显示模式。
  • VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME – 允许我们的应用程序以全屏独占模式显示,这对于 FreeSync HDR 是必需的。

需要注意的是,其中一些扩展是新的,您必须使用最新的 AMD 驱动程序/Vulkan SDK 才能访问它们。

在验证我们的设备具有上述扩展后,我们填充所有必需的 FreeSync HDR 结构以启用 FreeSync HDR,如 FreeSync2.cpp 中所示。

// VkSurfaceFullScreenExclusiveWin32InfoEXT
s_SurfaceFullScreenExclusiveWin32InfoEXT.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT;
s_SurfaceFullScreenExclusiveWin32InfoEXT.pNext = nullptr;
s_SurfaceFullScreenExclusiveWin32InfoEXT.hmonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);
// VkSurfaceFullScreenExclusiveInfoEXT
s_SurfaceFullScreenExclusiveInfoEXT.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT;
s_SurfaceFullScreenExclusiveInfoEXT.pNext = &s_SurfaceFullScreenExclusiveWin32InfoEXT;
s_SurfaceFullScreenExclusiveInfoEXT.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT;
// VkPhysicalDeviceSurfaceInfo2KHR
s_PhysicalDeviceSurfaceInfo2KHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
s_PhysicalDeviceSurfaceInfo2KHR.pNext = &s_SurfaceFullScreenExclusiveInfoEXT;
s_PhysicalDeviceSurfaceInfo2KHR.surface = surface;
// VkHdrMetadataEXT
s_HdrMetadataEXT.sType = VK_STRUCTURE_TYPE_HDR_METADATA_EXT;
s_HdrMetadataEXT.pNext = nullptr;
// VkDisplayNativeHdrSurfaceCapabilitiesAMD
s_DisplayNativeHdrSurfaceCapabilitiesAMD.sType = VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD;
s_DisplayNativeHdrSurfaceCapabilitiesAMD.pNext = &s_HdrMetadataEXT;
// VkSurfaceCapabilities2KHR
s_SurfaceCapabilities2KHR.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
s_SurfaceCapabilities2KHR.pNext = &s_DisplayNativeHdrSurfaceCapabilitiesAMD;
VkResult res = g_vkGetPhysicalDeviceSurfaceCapabilities2KHR(s_physicalDevice,
&s_PhysicalDeviceSurfaceInfo2KHR,
&s_SurfaceCapabilities2KHR);
assert(res == VK_SUCCESS);
// VkSwapchainDisplayNativeHdrCreateInfoAMD
s_SwapchainDisplayNativeHdrCreateInfoAMD.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD;
s_SwapchainDisplayNativeHdrCreateInfoAMD.pNext = &s_SurfaceFullScreenExclusiveInfoEXT;
s_SwapchainDisplayNativeHdrCreateInfoAMD.localDimmingEnable =
s_DisplayNativeHdrSurfaceCapabilitiesAMD.localDimmingSupport;

vkGetPhysicalDeviceSurfaceCapabilities2KHR 中,我们需要将 fullscreenExclusive 设置为 VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT

VkSurfaceFullScreenExclusiveWin32InfoEXT 中,我们需要将 hMonitor 设置为我们想要显示的显示器。在示例中,我们总是选择主显示器,但在实际游戏中,这应该由应用程序驱动。

然后我们调用 vkGetPhysicalDeviceSurfaceCapabilities2KHR,它将填充 s_SurfaceCapabilities2KHRs_DisplayNativeHdrSurfaceCapabilitiesAMDs_HdrMetadataEXTs_HdrMetadataEXT 包含显示器的原生色彩空间主色调、最小/最大亮度等 – 我们在之前的博客文章中讨论过的查询到的显示器数据。VkDisplayNativeHdrSurfaceCapabilitiesAMD 存储显示器是否支持局部调光。

最后,在 VkSwapchainDisplayNativeHdrCreateInfoAMD 中,如果我们的显示器支持局部调光,我们需要将 localDimmingEnable 设置为 true,否则设置为 false。这将用于稍后的交换链创建。

现在我们已经填写了所有 FreeSync HDR 结构,我们需要检查我们的表面是否支持 FreeSync HDR,如 FreeSync2.cpp 中所示。

bool fs2EnumerateDisplayModes(std::vector *pModes)
{
//...
// Get the list of formats
uint32_t formatCount;
VkResult res = g_vkGetPhysicalDeviceSurfaceFormats2KHR(s_physicalDevice,
&s_PhysicalDeviceSurfaceInfo2KHR,
&formatCount,
NULL);
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS)
return false;
std::vector surfFormats(formatCount);
for (UINT i = 0; i < formatCount; ++i)
{
surfFormats[i].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
}
res = g_vkGetPhysicalDeviceSurfaceFormats2KHR(s_physicalDevice,
&s_PhysicalDeviceSurfaceInfo2KHR,
&formatCount,
surfFormats.data());
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS)
return false;
for (uint32_t i = 0; i < formatCount; i++)
{
if (surfFormats[i].surfaceFormat.format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 &&
surfFormats[i].surfaceFormat.colorSpace == VK_COLOR_SPACE_DISPLAY_NATIVE_AMD)
{
pModes->push_back(DISPLAYMODE_FS2_Gamma22);
}
if (surfFormats[i].surfaceFormat.format == VK_FORMAT_R16G16B16A16_SFLOAT &&
surfFormats[i].surfaceFormat.colorSpace == VK_COLOR_SPACE_DISPLAY_NATIVE_AMD)
{
pModes->push_back(DISPLAYMODE_FS2_SCRGB);
}
}
//...
}

找到我们想要的显示格式后,我们通过 Windows® API 以独占全屏模式创建我们的窗口。这可以通过创建具有无边框全屏标志的窗口,并使其大小和分辨率与显示器匹配来实现。之后,我们使用下面的代码在 SwapChain.cpp 中创建我们的交换链。

// ...
VkSwapchainCreateInfoKHR swapchain_ci = {};
swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchain_ci.pNext = nullptr;
if (ExtFreeSync2AreAllExtensionsPresent())
{
swapchain_ci.pNext = GetVkSwapchainDisplayNativeHdrCreateInfoAMD();
}
swapchain_ci.surface = surface;
swapchain_ci.imageFormat = m_surfaceFormat.format;
swapchain_ci.imageColorSpace = m_surfaceFormat.colorSpace;
// ...
res = vkCreateSwapchainKHR(device, &swapchain_ci, NULL, &m_swapChain);
assert(res == VK_SUCCESS);

常规交换链创建与 FreeSync HDR 交换链创建之间的主要区别在于:

  • 在设置交换链的表面格式时,我们需要使用 FreeSync HDR 表面格式。
  • 我们需要将 VkSwapchainDisplayNativeHdrCreateInfoAMD 结构提供给我们的 pNext 变量,其中包含从 vkGetPhysicalDeviceSurfaceCapabilities2KHR 查询到的值。这将使我们的交换链能够在我们选择的显示器上获得独占全屏,并且还将设置我们是否可以从此交换链启用/禁用局部调光。
  • 需要注意的是,为了成功获取独占全屏,窗口的宽度、高度以及交换链的表面范围需要与显示器的分辨率匹配。

我们的交换链使用的 FreeSync HDR 显示模式由我们传入的表面格式和色彩空间决定。我们在检查表面是否支持我们想要的 FreeSync HDR 显示模式时设置这些。

最后一步是获取我们显示器的全屏独占模式,并将我们交换链的色彩空间设置为显示器的原生色彩空间。

vkAcquireFullScreenExclusiveModeEXT(device, swapchain);
vkSetHdrMetadataEXT(device, swpachainCount, swapChain, &s_HdrMetadataEXT);

我们首先调用 vkAcquireFullScreenExclusiveModeEXT 来赋予我们的应用程序全屏独占控制权。

然后我们使用查询到的 s_HdrMetadataEXT 结构调用 vkSetHdrMetadataEXT,这将启用我们交换链上的 FreeSync HDR 色彩空间,并完成我们在 Vulkan 中的设置过程。

在实际游戏中,玩家通常有选项来更改游戏正在渲染的显示器,或是否处于 FreeSync HDR 模式。当发生此类更改时,将需要重新创建交换链,并且我们将不得不再次检查显示格式支持,以及如果我们更改了正在渲染的显示器,则重新查询显示器的元数据。实例扩展不需要重新查询,设备扩展也不需要,除非我们正在更改正在运行的 GPU。

要更改局部调光设置,我们可以使用以下函数。

vkSetLocalDimmingAMD(m_swapChain, localDimmingEnable);

更改局部调光后,我们需要重新查询 HDR 元数据,并需要再次设置 HDR 元数据,以便我们拥有显示器正确的最大亮度值。

最后一步是向色调映射器提供显示器亮度数据,向色域映射器提供显示器的色度值,并使用查询到的 VkHdrMetadataEXT 结构以正确的 FreeSync HDR 格式对最终帧缓冲区进行编码。色调和色域映射器是游戏特定的,因此我们无法详细介绍如何集成它们,因为它在每个引擎中都不同。但是,我们将在下面的 FreeSync HDR 显示格式部分的 HLSL 代码 中介绍如何编码最终帧缓冲区的颜色。

用于 FreeSync HDR 显示格式的着色器代码

第一篇文章中,我们回顾了每种 FreeSync HDR 显示格式的帧缓冲区颜色编码的不同要求。在这里,我们将展示在帧缓冲区呈现到屏幕之前(ColorConversionPS.hlsl)每个像素运行的着色器代码。着色器接收编码为 Rec709 的每个像素的颜色作为输入,并输出编码为所选 FreeSync HDR 显示格式的颜色。

switch (u_displayMode)
{
// ...
case 1:
{
// FS2_Gamma22
// Convert to display native color space ie the value queried from AGS
color.xyz = mul(u_contentToMonitorRecMatrix, color).xyz;
// Apply gamma
color.xyz = pow(color.xyz, 1.0f / 2.2f);
break;
}
case 2:
{
// FS2_scRGB
// Scale to maxdisplayLuminanace / 80
// In this case luminanace value queried from AGS
color.xyz = (color.xyz * (u_displayMaxLuminancePerNits - u_displayMinLuminancePerNits))
+ u_displayMinLuminancePerNits;
break;
}
}

我们设置了一个 switch 语句,根据我们的 FreeSync HDR 显示模式对每种颜色进行编码。

  • 对于 FS2_Gamma22,我们乘以一个矩阵,该矩阵将颜色从 Rec709 转换为显示器的原生色彩空间。然后我们应用反伽马曲线,然后将像素发送到显示器。如果我们的输入颜色是 Rec2020,我们则构建一个矩阵将 Rec2020 转换为显示器原生,而不是 Rec709 转换为显示器原生。
  • 对于 FS2_scRGB,我们已经将颜色编码为 Rec709,因此我们将每个通道乘以 nits / 80 的动态范围。例如,如果颜色存储在 Rec2020 中,我们将在这一步将其转换为 Rec709。

要计算将颜色从 Rec709 转换为显示器原生色彩空间的矩阵,我们使用以下代码,如 ColorConversion.cpp 中所示。

XMFLOAT3X3 CalculateDisplayXYZToRGBMatrix(float xw, float yw, float xr, float yr,
float xg, float yg, float xb, float yb)
{
// ref: http://www.brucelindbloom.com/index.html?Math.html
float Xw = xw / yw;
float Yw = 1;
float Zw = (1 - xw - yw) / yw;
float Xr = xr / yr;
float Yr = 1;
float Zr = (1 - xr - yr) / yr;
float Xg = xg / yg;
float Yg = 1;
float Zg = (1 - xg - yg) / yg;
float Xb = xb / yb;
float Yb = 1;
float Zb = (1 - xb - yb) / yb;
XMFLOAT3X3 XRGB = XMFLOAT3X3(Xr, Xg, Xb, Yr, Yg, Yb, Zr, Zg, Zb);
XMFLOAT3X3 XRGBInverse = Inv3X3Mat(XRGB);
XMFLOAT3 referenceWhite = XMFLOAT3(Xw, Yw, Zw);
XMFLOAT3 SRGB = MUL3X3MatWithVec3(XRGBInverse, referenceWhite);
XMFLOAT3X3 displayRGBToXYZMatrix = XMFLOAT3X3(SRGB.x * Xr, SRGB.y * Xg, SRGB.z * Xb, SRGB.x * Yr,
SRGB.y * Yg, SRGB.z * Yb, SRGB.x * Zr, SRGB.y * Zg, SRGB.z * Zb);
return Inv3X3Mat(displayRGBToXYZMatrix);
}
// ...
XMFLOAT3X3 rec709RGBToXYZ = XMFLOAT3X3(0.4124564f, 0.3575761f, 0.1804375f,
0.2126729f, 0.7151522f, 0.0721750f,
0.0193339f, 0.1191920f, 0.9503041f);
XMFLOAT3X3 XYZToDisplayNative = CalculateDisplayXYZToRGBMatrix(0.312f, 0.329f,
monitorDisplayPrimaryRed.x, monitorDisplayPrimaryRed.y,
monitorDisplayPrimaryGreen.x, monitorDisplayPrimaryGreen.y,
monitorDisplayPrimaryBlue.x, monitorDisplayPrimaryBlue.y);
XMFLOAT3X3 rec709ToDisplayNative = Mul3X3MatWith3X3Mat(XYZToDisplayNative, rec709RGBToXYZ);

在上面的代码中,我们创建一个将颜色从 Rec709 转换为 XYZ 的矩阵,并创建一个将颜色从 XYZ 转换为 DisplayNative 的第二个矩阵。

接下来,我们乘以这两个矩阵,将线性变换合并为一个矩阵,然后将其发送到 GPU 以在着色器中使用。

我们使用一个辅助函数,该函数在给定 RGB 色彩空间的原始值时生成 XYZ 到 RGB 的矩阵;这些值从 FreeSync HDR 显示器查询。辅助函数的数学公式来源于 http://www.brucelindbloom.com/index.html?Math.html

需要注意的是,在上面的着色器代码中,我们没有对颜色进行色域映射,我们只是将它们编码为 FreeSync HDR 显示格式所需的色彩空间。在实际游戏中,如果我们应用色域映射器,我们的颜色在色域映射后应该已经编码为显示器的原生色彩空间,因此我们可以简单地在 FreeSync2_Gamma22 中提供数据。

在遵循以上所有步骤后,您现在应该已将 FreeSync HDR 集成到您的游戏中,并支持您所需的 FreeSync HDR 显示格式!

结论

至此,FreeSync HDR 博客文章系列告一段落。我们回顾了 FreeSync HDR 是什么,它解决了什么问题,如何将其集成到各种后期处理通道中,以及每个显式 API 的代码演练。

我们希望本系列文章能帮助您更好地理解 FreeSync HDR 是什么以及如何在您的应用程序中使用它。

阅读更多

您可以在 FidelityFX™ Luminance Preserving Mapper (LPM) 中找到 FreeSync HDR 的示例用法。

阅读我们关于 AMD FreeSync Premium Pro HDR 的其他详细教程,以获得深入的了解。

Ihor Szlachtycz's avatar

Ihor Szlachtycz

指向第三方网站的链接仅为方便起见提供,除非明确说明,否则 AMD 对这些链接网站的内容概不负责,也不表示认可。

相关新闻和技术文章

相关视频

© . This site is unofficial and not affiliated with AMD.