360全景图划分成 TILE
.
高纬度按 4:1
下采样. 中纬度按 2:1
下采样. 低纬度 1:1
渲染时,高纬度按 1:4
还原. 中纬度按 1:2
还原.
SIMD,single instruction multiple data,单指令流多数据流,一次运算指令可以执行多个数据流.
使用指令集进行并行优化.
SSE本质上类似于一个向量处理器,包括了4个主要部分
Intrinsic使用的数据类型和其寄存器是相对应
Intrinsic 函数的命名:
Intrinsic函数的命名也是有一定的规律的,一个Intrinsic通常由3部分构成,这个三个部分的具体含义如下:
SSE浮点运算分为两大类, packed
和 scalar
packed指令是一次对XMM暂存器中的四个浮点数(DATA0~DATA3)均进行计算,而scalar只对XMM暂存器中的DATA0进行计算,见下图。
ARMV7架构包含:
16个通用寄存器(32bit),R0-R15
16个NEON寄存器(128bit),Q0-Q15(同时也可以被视为32个64bit的寄存器,D0-D31)
16个VFP寄存器(32bit),S0-S15
NEON和VFP的区别在于VFP是加速浮点计算的硬件不具备数据并行能力,同时VFP更尽兴双精度浮点数(double)的计算,NEON只有单精度浮点计算能力。更多请参考stackoverflow:neon vs vfp
64bit数据类型,映射至寄存器即为D0-D31
128bit数据类型,映射至寄存器即为Q0-Q15
下面这些数据类型是上述基本数据类型的组合而成的结构化数据类型,通常为被映射到多个寄存器中。
typedef struct int8x8x2_t
{
int8x8_t val[2];
} int8x8x2_t;
...
//省略...
...
#ifdef __ARM_FEATURE_CRYPTO
typedef struct poly64x2x4_t
{
poly64x2_t val[4];
} poly64x2x4_t;
#endif
NEON指令按照操作数类型可以分为正常指令、宽指令、窄指令、饱和指令、长指令。
NEON指令按照作用可以分为:加载数据、存储数据、加减乘除运算、逻辑AND/OR/XOR运算、比较大小运算等
// 宏定义: 以空间换时间.. 小心使用..
// ---------PC端:SSE指令集----------------
// 高纬度的1:4 拷贝 4字节->16
#define set4(output_buf_y,input_buf_y) {\
__m128i itmp1 = _mm_loadl_epi64((__m128i*)(input_buf_y));\
__m128i itmp2 = _mm_unpacklo_epi8(itmp1, itmp1);\
__m128i dst = _mm_unpacklo_epi8(itmp2, itmp2);\
__m128i* otmp = (__m128i*)(output_buf_y);\
_mm_store_si128(otmp, dst);\
}
// 中纬度的1:2 拷贝 8字节->16
#define set2(output_buf_y,input_buf_y) {\
__m128i itmp =_mm_loadl_epi64((__m128i*)(input_buf_y));\
__m128i* otmp = (__m128i*)(output_buf_y);\
_mm_store_si128(otmp, _mm_unpacklo_epi8(itmp, itmp));\
}
// ---------Android端:NEON指令集----------------
#define NEON_INTRINSICS 1// 1:neon内联函数 0:汇编
#if NEON_INTRINSICS
//1:4 拷贝 8->32
#define set4(output_buf_y,input_buf_y) {\
uint8x8x4_t v;\
v.val[0] = vld1_u8(input_buf_y);\
v.val[1] = v.val[0];\
v.val[2] = v.val[0];\
v.val[3] = v.val[0];\
vst4_u8(output_buf_y,v);\
}
// 1:2 拷贝 8字节->16
#define set2(output_buf_y,input_buf_y) {\
uint8x8x2_t v;\
v.val[0] =vld1_u8(input_buf_y);\
v.val[1] = v.val[0];\
vst2_u8(output_buf_y,v);\
}
#else
// 汇编版本
void set4(unsigned char * output_buf_y,unsigned char * input_buf_y) {\
__asm__(\
"VLD1.8 {d0},[r1] \t\n"\
"VMOV d1,d0 \t\n"\
"VMOV d2,d0 \t\n"\
"VMOV d3,d0 \t\n"\
"VST4.8 {d0, d1, d2, d3}, [r0]"\
);\
}
void set2(unsigned char *output_buf_y,unsigned char *input_buf_y) {\
__asm__(\
"VLD1.8 {d0},[r1] \t\n"\
"VMOV d1,d0 \t\n"\
"VST2.8 {d0, d1}, [r0]"\
);\
}
#endif
英特尔之SSE指令集指南
NEON各函数介绍
ARM NEON 编程系列
Android-NDK之Hello Neon