Vulkan 规范说:
VK_FORMAT_R16G16_S10_5_NV 指定两部分定点格式,其中最高有效位指定符号位,接下来的 10 位指定整数值,最后 5 位表示小数值。
我不确定这是否意味着它是2的补码格式?例如,-1.5 表示为:
0b1'0000000001'1000
(即符号= 1,10位整数部分= 1,5位小数部分= 16)
或
0b1'1111111110'1000
(即11位2的补码,5位小数部分= 16,或者换句话说,2的48的补码)
简单来说就是2的补码。
在 NVidia 的 SDK 示例中,他们有一些提示。在 NvOFUtilsVulkan.cpp 中,它们有一个格式转换函数,将 VK_FORMAT_R16G16_S10_5_NV 与 NV_OF_BUFFER_FORMAT_SHORT2 相关联。在 NvOF.cpp 中,它们将 NV_OF_BUFFER_FORMAT_SHORT2 格式与 NV_OF_FLOW_VECTOR 结构相关联。该结构的文档将格式描述为 S10.5,并且在 论坛帖子 中,来自 NVidia 的某人引用了此定点简介,其中描述了 2s 补码格式。
在示例中,他们在
NvOFDataLoader.cpp中还有一个(损坏的)
convertFloat2Fixed
函数。
void NvOFDataLoaderFlo::convertFloat2Fixed(const float* pFlowFloat, NV_OF_FLOW_VECTOR* pFlowFixed)
{
for (uint32_t y = 0; y < m_height; ++y)
{
for (uint32_t x = 0; x < m_width; ++x)
{
pFlowFixed[y * m_width + x].flowx = static_cast<uint16_t>(pFlowFloat[(y * 2 * m_width) + 2 * x] * m_precision);
pFlowFixed[y * m_width + x].flowy = static_cast<uint16_t>(pFlowFloat[(y * 2 * m_width) + 2 * x + 1] * m_precision);
}
}
}
考虑到它主要是为了在 x86 系统上运行,这强烈表明它是 2 的补码。也就是说,首先转换为
int16_t
,因为将负浮点数转换为无符号整数是 UB,并且在使用负常量时会主动中断。