您的位置:首页 > 移动开发

Apple A4之NEON技术——颜色混合算法

2010-10-06 23:32 316 查看
本人之前在介绍Apple's OpenCL的时候出过一份代码,是用于图像半透明算法的,并且提供了OpenCL版本与x86的SSE版本。 这次,俺将提供ARMv7架构的NEON版本进行对照。通过对比,各位可以清晰地看到ARMv7架构具有比传统的x86拥有更强的计算能力。在处理器拥有相同的流水线特征的情况下,ARMv7能提供更精简,更强大的计算性能。



首先提供初始化以及应用的主程序:

#define IMAGE_X_PIXELS          176
#define IMAGE_Y_PIXELS          144
extern void ZennySetCoefficient(const float *coef0, const float *coef1);
extern void ZennyBlend(const float *image1, const float *image2, float *dst, size_t length);
static inline size_t address_align(size_t addr, int nBytesAligned)
{
    return (addr & ~(nBytesAligned - 1)) + nBytesAligned;
}
- (IBAction)v128LoadButtonPressed:(id)sender
{
    const int count = IMAGE_X_PIXELS * IMAGE_Y_PIXELS;
    const float coef1 = 0.4f, coef2 = 0.6f;
    
    float *pOrgSrc1 = (float*)malloc(count * sizeof(*pOrgSrc1) + 64);
    float *pOrgSrc2 = (float*)malloc(count * sizeof(*pOrgSrc1) + 64);
    float *pOrgDst = (float*)malloc(count * sizeof(*pOrgSrc1) + 64);
    float *pValidateDst = (float*)malloc(count * sizeof(*pOrgSrc1));
    
    float *pSrc1 = (float*)address_align((size_t)pOrgSrc1, 64);
    float *pSrc2 = (float*)address_align((size_t)pOrgSrc2, 64);
    float *pDst = (float*)address_align((size_t)pOrgDst, 64);
    
    for(int i = 0; i < count; i++)
    {
        pSrc1[i] = rand();
        pSrc2[i] = rand();
    }
    
    // Prepare for validation
    for(int i = 0; i < count; i++)
        pValidateDst[i] = pSrc1[i] * coef1 + pSrc2[i] * coef2;
    
    ZennySetCoefficient(&coef1, &coef2);
    
    ZennyBlend(pSrc1, pSrc2, pDst, count);
    
    // Validate
    for(int i = 0; i < count; i++)
    {
        if(pValidateDst[i] != pDst[i])
        {
            [outputText setText:[NSString stringWithFormat:@"Error ocurred @: %d", i]];
            return;
        }
    }
    
    [outputText setText:@"Successful!"];
    
    free(pOrgSrc1);
    free(pOrgSrc2);
    free(pOrgDst);
    free(pValidateDst);
}


上述代码含有iOS的Objective-C接口,但是这并不会影像我们的阅读理解。



下面是外部接口ZennySetCoefficient

// extern void ZennySetCoefficient(const float *coef0, const float *coef1);
_ZennySetCoefficient:
    vld1.32     {d4[], d5[]}, [r0]
    vld1.32     {d6[], d7[]}, [r1]
    
    bx          lr


这个接口用于将混合系数分别传给q2、q3寄存器



下面则是核心的利用NEON技术的代码:

// extern void ZennyBlend(const float *image1, const float *image2, float *dst, size_t length);
_ZennyBlend:
    
READ_CALC_WRITE:
    vld2.32     {d0, d1}, [r0]!
    vld2.32     {d2, d3}, [r1]!
    
    vmul.f32    q0, q0, q2
    vmla.f32    q0, q1, q3
    
    vst2.32     {d0, d1}, [r2]!
    
    subs        r3, r3, #4
    bne         _ZennyBlend
    
    bx          lr


代码很简短,但是提供的功能已经很强大了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: