1

你好,我有一些 c 程序:

    inline float intersectRaySphere(float3* rayO, float3* rayV, float3* sO, float sR)
    {
    static float3 Q;

    Q = sub(sO,rayO);

    float cc = dot(&Q,&Q);
    float v = dot(&Q,rayV);
    float d = sR*sR - (cc - v*v);

    // If there was no intersection, return -1
    if (d < 0.0) return (-1.0f);
    // Return the distance to the [first] intersecting point
    return (v - sqrt(d));
    }

我试图用 x86 fpu asm 重写它并创建这样一个

    _asm_intersectRaySphere:; Function begin
    push    ebp                                     ; 0000 _ 55
    mov     ebp, esp                                ; 0001 _ 89. E5
    add     esp, -20                                ; 0003 _ 83. C4, EC
    mov     eax, dword [ebp+8H]                     ; 0006 _ 8B. 45, 08
    mov     ecx, dword [ebp+0CH]                    ; 0009 _ 8B. 4D, 0C
    mov     edx, dword [ebp+10H]                    ; 000C _ 8B. 55, 10
    fld     dword [edx]                             ; 000F _ D9. 02
    fsub    dword [eax]                             ; 0011 _ D8. 20
    fld     dword [edx+4H]                          ; 0013 _ D9. 42, 04
    fsub    dword [eax+4H]                          ; 0016 _ D8. 60, 04
    fld     dword [edx+8H]                          ; 0019 _ D9. 42, 08
    fsub    dword [eax+8H]                          ; 001C _ D8. 60, 08
    fld     st2                                     ; 001F _ D9. C2
    fmul    st0, st(0)                              ; 0021 _ DC. C8
    fld     st2                                     ; 0023 _ D9. C2
    fmul    st0, st(0)                              ; 0025 _ DC. C8
    fld     st2                                     ; 0027 _ D9. C2
    fmul    st0, st(0)                              ; 0029 _ DC. C8
    faddp   st1, st(0)                              ; 002B _ DE. C1
    faddp   st1, st(0)                              ; 002D _ DE. C1
    fld     dword [ecx]                             ; 002F _ D9. 01
    fmul    st(0), st4                              ; 0031 _ D8. CC
    fld     dword [ecx+4H]                          ; 0033 _ D9. 41, 04
    fmul    st(0), st4                              ; 0036 _ D8. CC
    fld     dword [ecx+8H]                          ; 0038 _ D9. 41, 08
    fmul    st(0), st4                              ; 003B _ D8. CC
    faddp   st1, st(0)                              ; 003D _ DE. C1
    faddp   st1, st(0)                              ; 003F _ DE. C1
    fst     dword [ebp-4H]                          ; 0041 _ D9. 55, FC
    fmul    st0, st(0)                              ; 0044 _ DC. C8
    fld     dword [ebp+14H]                         ; 0046 _ D9. 45, 14
    fmul    st0, st(0)                              ; 0049 _ DC. C8
    faddp   st1, st(0)                              ; 004B _ DE. C1
    fsubrp  st1, st(0)                              ; 004D _ DE. E1
    fxch    st3                                     ; 004F _ D9. CB
    fstp    st0                                     ; 0051 _ DD. D8
    fstp    st0                                     ; 0053 _ DD. D8
    fstp    st0                                     ; 0055 _ DD. D8
    ftst                                            ; 0057 _ D9. E4
    fwait                                           ; 0059 _ 9B
    fnstsw  ax                                      ; 005A _ DF. E0
    fwait                                           ; 005C _ 9B
    sahf                                            ; 005D _ 9E
    jc      ?_001                                   ; 005E _ 72, 07
    fsqrt                                           ; 0060 _ D9. FA
    fsubr   dword [ebp-4H]                          ; 0062 _ D8. 6D, FC
    jmp     ?_002                                   ; 0065 _ EB, 06

     ?_001:  
    fstp    st0                                     ; 0067 _ DD. D8
    fld1                                            ; 0069 _ D9. E8
    fchs                                            ; 006B _ D9. E0
     ?_002:  
    mov     esp, ebp                                ; 006D _ 89. EC
    pop     ebp                                     ; 006F _ 5D
    ret                                             ; 0070 _ C3
    ; _asm_intersectRaySphere End of function

经过测试,它工作正常,c 例程大约需要 150 个周期(在我 6 或 7 岁的奔腾 4 上),我的 asm 例程大约需要 66 个周期(*) - 所以这是一个很好的改进,但也许它也可以还是有所改善?

tnx

(*)我在随机输入数据上测试时不太小心,所以可能是“非交叉”原因 - 不涉及 sqrt

4

1 回答 1

1

我会替换这个:

fstp st0
fstp st0
fstp st0
ftst
fwait
fnstsw  ax
fwait
sahf
jc ?__001

这样:

fcompp
fstp st0
fldz
fcomip st0, st1
ja ?__001

fnstsw不是很快,sahf也不是很好,尤其是在 P4 上。如果你不能使用fcomi(即如果它必须在 P1 或 PMMX 上工作),你仍然可以sahf通过直接测试来跳过ax

于 2012-08-20T14:10:24.287 回答