Vulkan没有默认帧缓冲区的概念,在送显上屏之前,需要一个基础结构来持有一些缓冲区。Vulkan引入了交换链的概念。
交换链本质上就是一个(用于送显上屏)图像的等待队列。应用程序获取一个图像,绘制内容,然后返回到队列。队列如何工作,队列中图像如何送显上屏 取决于交换链的配置参数。
交换链的作用就是同步图像的上屏和屏幕的刷新。
0 Surface的校验
验证GPU是否支持surface的显示,vulkan标准内没有窗体surface的概念,外在的因素不可控所以要校验,
// Section1: check
VkBool32 vk_queue_family_supports_present = false;
auto hr = vkGetPhysicalDeviceSurfaceSupportKHR(device.gpuDevice_, device.queueFamilyIndex_, device.surface_, &vk_queue_family_supports_present);
if (hr != VK_SUCCESS || !vk_queue_family_supports_present) {
LOGE("surface not founded...");
exit(1);
}
这个接口第二个参数是queue的索引,多个队列需要循环遍历,手机上一般1个队列有效。
1 Surface Format相关
同样手段,先取长度 再填充vector。
// Query the list of supported surface format and choose one we like
uint32_t formatCount = 0;
hr = vkGetPhysicalDeviceSurfaceFormatsKHR(device.gpuDevice_, device.surface_,
&formatCount, nullptr);
if (hr != VK_SUCCESS || formatCount == 0) {
LOGE("could not get number of physical device formats for device");
exit(1);
}
std::vector<VkSurfaceFormatKHR> formats; formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device.gpuDevice_, device.surface_,
&formatCount, formats);
LOGI("Got %d formats", formatCount);
// 至少必须有RGBA8888啊,
uint32_t chosenFormat;
for (chosenFormat = 0; chosenFormat < formatCount; chosenFormat++) {
if (formats[chosenFormat].format == VK_FORMAT_R8G8B8A8_UNORM) break;
}
assert(chosenFormat < formatCount);
surfaceFormat结构里有两个字段,pixelFormat和colorSpace:
- 格式主要sRGB最常见的,SCRGB是FP16表示每个通道,R16G16B16A16。RGB也有两种:最普通的UNORM,和非线性的,后者非常少见。
- 颜色空间,分线性和非线性的。
关于线性&非线性&HDR的vkSurface format的设置,参考下openharmony中graphics3d模块的代码:
VkFormat GetColorFormat(const uint32_t flags, const vector<VkSurfaceFormatKHR>& surfaceFormats)
{
constexpr uint32_t preferredFormatCount { 4u };
constexpr VkFormat srgbFormats[preferredFormatCount] = { VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_B8G8R8A8_SRGB,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM };
constexpr VkFormat nonSrgbFormats[preferredFormatCount] = { VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_B8G8R8A8_SRGB };
constexpr VkFormat hdrFormats[] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32,
VK_FORMAT_R16G16B16A16_SFLOAT };
// If pSurfaceFormats includes just one entry, whose value for format is VK_FORMAT_UNDEFINED,
// surface has no preferred format. In this case, the application can use any valid VkFormat value.
if (surfaceFormats[0].format == VK_FORMAT_UNDEFINED && surfaceFormats.size() == 1) {
return VK_FORMAT_R8G8B8A8_SRGB;
}
if (flags & SwapchainFlagBits::CORE_SWAPCHAIN_HDR_BIT) {
for (auto format : hdrFormats) {
for (auto surfaceFormat : surfaceFormats) {
if (format == surfaceFormat.format) {
return surfaceFormat.format;
}
}
}
}
const bool preferSrgbFormat = (flags & SwapchainFlagBits::CORE_SWAPCHAIN_SRGB_BIT);
const array_view<const VkFormat> formats =
(preferSrgbFormat) ? array_view<const VkFormat> { srgbFormats } : array_view<const VkFormat> { nonSrgbFormats };
for (auto format : formats) {
for (auto surfaceFormat : surfaceFormats) {
if (format == surfaceFormat.format) {
return surfaceFormat.format;
}
}
}
return VK_FORMAT_UNDEFINED;
}
关于这两个概念补充一段:
Vulkan 本身与色彩空间无关。不过,在数字电信号转换为光信号之前的某个阶段,色彩空间必须明确。这就是在交换链创建过程中需要指定色彩空间的原因。
- imageFormat指定图像格式是什么(与vkCreateImage()中的作用相同)。
- imageColorSpace则表示在图像呈现时,交换链 / 显示器对这些数值的解释方式。
所以,如果使用UNORM,这意味着色彩空间未指定,数据只是普通的原始数据位。或者更确切地说,这意味着由你来负责色彩空间(前提是图像确实存储颜色信息,而不是完全其他类型的数据)。
如果你将VK_COLOR_SPACE_SRGB_NONLINEAR_KHR与_UNORM搭配使用,这意味着交换链获取你的数据位,并在呈现时假定这些数据已经是sRGB 格式。
如果使用的是_SRGB,那么对于交换链本身来说没有区别,但实际情况是创建的VkImages是_SRGB格式,这意味着当你使用它们时,颜色会为你进行线性化处理(与创建非交换链的VkImage时的情况相同)。
扩展一下,谈谈色域。显示器的能力,依赖于硬件是否支持,最广泛和古老的格式是sRGB,P3(广色域),BT2020,HDR10,杜比,后面几种在HDR渲染中经常遇到,目前旗舰手机都支持hdr,iphone12是第一款集采集、处理、显示的终端设备。
要正常渲染,至少得有一种格式,R8G8B8A8_UNORM,否则就退出。P40Pro手机查询到支持5种格式,
(VkSurfaceFormatKHR) (format = VK_FORMAT_R8G8B8A8_UNORM, colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
(VkSurfaceFormatKHR) (format = VK_FORMAT_R8G8B8A8_SRGB, colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
(VkSurfaceFormatKHR) (format = VK_FORMAT_R5G6B5_UNORM_PACK16, colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
(VkSurfaceFormatKHR) (format = VK_FORMAT_R16G16B16A16_SFLOAT, colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
(</

2072

被折叠的 条评论
为什么被折叠?



