青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Raytrace world

Chaos 的光線跟蹤世界

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  4 隨筆 :: 0 文章 :: 63 評論 :: 0 Trackbacks

Chaos on Graphics

About 數(shù)學(xué)庫之一 SSE/SSE2

 

Chaos Chiao

 

 

毫無疑問,數(shù)學(xué)庫是圖形程序的基石,是圖形程序運(yùn)行效率的關(guān)鍵之一。一個優(yōu)秀的數(shù)學(xué)庫可以讓圖形程序運(yùn)行得更流暢,甚至要快上幾十倍上百倍。有時候替換一條除法運(yùn)算會帶來成倍的效率增長,比如用乘以 1/op 替換 vector 里的 operator /。當(dāng)然,更高級的優(yōu)化是使用 SIMD 優(yōu)化海量運(yùn)算,這就是本文的中心——SSE/SSE2 優(yōu)化。

在描述 SSE/SSE2 優(yōu)化前,我先介紹一般的 vector/matrix 庫構(gòu)造。當(dāng)然,在 OpenEXR 里已經(jīng)有一個非常優(yōu)秀的 Imath 實(shí)現(xiàn)了,數(shù)學(xué)庫的實(shí)現(xiàn)細(xì)節(jié)可以參照它。

在圖形程序里我們經(jīng)常會遇到向量運(yùn)算,這是標(biāo)準(zhǔn)C++編譯器所不能直接支持的,如三維空間向量。傳統(tǒng)的C圖形程序會使用“數(shù)組+宏”的實(shí)現(xiàn)方式:

 

typedef float vector[3];

  

到了C++時代,一般會封裝成:

 

class Vector

{

private:

    float x , y , z;

};

 

然后加入通常的各種method,如

 

const float& X( void ) const {

    return x;

}

 

標(biāo)準(zhǔn)的向量算法如內(nèi)積、外積、單位化、長度、運(yùn)算等等,都可以封裝為成員函數(shù)。

 

Vector operator + ( const Vector& a , const float & b ) {

    return Vector( a.x + b , a.y + b , a.z + b );

}

 

類似的數(shù)學(xué)庫可以在Aqsis等一些開源的圖形程序里找到。不過這些結(jié)構(gòu)并不適合接下來我們要討論的SSE/SSE2優(yōu)化。

 

SSE – Streaming SIMD Extension,是IntelPIII開始加入的一種x86擴(kuò)展指令集。在SSE以前,x86的浮點(diǎn)運(yùn)算都是以棧式FPU完成的,有一定x86匯編經(jīng)驗(yàn)的人應(yīng)該不會對那些復(fù)雜的fldfst指令陌生吧。而SSE一方面讓浮點(diǎn)運(yùn)算可以像整數(shù)運(yùn)算的模式、如 add eax , ebx 那樣通過直接訪問寄存器完成,繞開了討厭的棧,另一方面引入了SIMD這個概念。SIMD – Single Instruction Multiply Data,顧名思義,它可以同時讓一條指令在多個數(shù)據(jù)上執(zhí)行,這種體系結(jié)構(gòu)在一度在大型機(jī)上非常流行,需要經(jīng)常進(jìn)行海量運(yùn)算的大型機(jī)器通常會通過一個數(shù)學(xué)SIMD虛擬機(jī)加快處理速度,比如同時讓一組數(shù)據(jù)執(zhí)行一個變換,數(shù)據(jù)的規(guī)模有上百萬之巨,而SIMD則可以優(yōu)化數(shù)據(jù)的存儲與運(yùn)算,減免某些切換Context的開銷。

在硬件層面上面支持SIMD,某程度是因游戲需要的驅(qū)使,因?yàn)樵絹碓蕉嗟?/SPAN>3D游戲涉及大量的向量操作,一般的浮點(diǎn)運(yùn)算優(yōu)化已經(jīng)不能再適應(yīng)這種并行運(yùn)算的需要了,而直接從指令上支持SIMD操作則可以進(jìn)一步簡化向量運(yùn)算的優(yōu)化,提高指令執(zhí)行效率。像 addps 這樣的SSE指令,可以并行執(zhí)行四個32位浮點(diǎn)數(shù)的加法運(yùn)算,而延遲只有4 cycle;相比之下,原來的fadd指令光執(zhí)行一個32位單精度浮點(diǎn)數(shù)加法的延遲已經(jīng)達(dá)到了3 cycle了,還沒計算fst等存儲指令的延遲。(具體見后面的指令執(zhí)行單元表)

顯然,SSE能給圖形程序帶來極大的優(yōu)化,其提高遠(yuǎn)勝于基于整數(shù)的MMX與雙單元單精度浮點(diǎn)數(shù)的3DNow!。但SSE對數(shù)據(jù)組織的要求是苛刻的,若要發(fā)揮SSE的最大威力,我們還需要進(jìn)行對齊向量數(shù)據(jù),把向量對齊到16字節(jié)。如果我們正在使用一般的三分量向量,那么就意味著有要浪費(fèi)四分之一的存儲空間來換取速度。當(dāng)然,這4字節(jié)還可以有很多用途,只是你必須處理得非常小心,因?yàn)槿魏芜\(yùn)算都將同時應(yīng)用到四個分量上。

要使用SSE,必須先確認(rèn)你的編譯器是否支持新的指令集。VC6 sp6VC.net.net 2003ICLGCC nasm 都支持SSE指令集。我推薦使用ICL,它的優(yōu)化做得最棒,生成的指令最緊湊、效率最高。使用SSE有兩種途徑,一是直接編寫匯編代碼,但難度較大,需要有一定的匯編經(jīng)驗(yàn);二是使用SSE intrinsic,一種直接在C/C++里使用SSE指令的偽函數(shù)調(diào)用。在圖形運(yùn)算的核心環(huán)節(jié)上、如raytrace核心,我建議使用匯編,這樣才能極大地體現(xiàn)出SSE的優(yōu)勢、與x86指令混合使用,并充分使用它的并行性。而在大多數(shù)場合下則推薦使用intrinsic,它的可讀性高,而且編譯器會在最后把函數(shù)調(diào)用替換成SSE指令,這樣既不需要寫內(nèi)嵌匯編代碼,又可以保證代碼的執(zhí)行效率。

 

下面將通過幾個簡單的運(yùn)算例子介紹SSE intrinsic的使用。首先,使用SSE需要一個新的頭文件

 

#include

 

里面定義了一個新的數(shù)據(jù)類型,__m128,這是一個128位、4個32位單精度浮點(diǎn)數(shù)的結(jié)構(gòu),如果你正在使用VC.net,你會看到它是一個關(guān)鍵字,被當(dāng)作一種基本數(shù)據(jù)類型。要是你不打算使用匯編SSE,那么就沒必要深究編譯器在幕后到底如何處理__m128類型的數(shù)據(jù),你只需要知道里面能存放四個float,而這四個float可以進(jìn)行并行運(yùn)算。

在定義了__m128后,文件聲明一大堆對__m128進(jìn)行運(yùn)算的函數(shù),如_mm_add_ps_mm_sub_ps等等,這就是SSE運(yùn)算指令的聲明。使用SSE優(yōu)化在這些聲明的幫助下變得非常簡單,如計算兩個向量之和,平時需要每一個元素進(jìn)行一次加法運(yùn)算,現(xiàn)在只需要簡單地:

 

__m128 a , b , c;

c = _mm_add_ps( a , b );

 

這樣等價于:

 

float a[4] , b[4] , c[4];

for( int i = 0 ; i < 4 ; ++ i )

    c[i] = a[i] + b[i];

 

但前者的運(yùn)算是并行的,在一般情況下效率遠(yuǎn)比后者要高。況且在描述復(fù)雜的運(yùn)算的時候,如:

 

       a = b * c + d / e;

 

則可以直接寫成:

 

__m128 a = _mm_add_ps( _mm_mul_ps( b , c ) , _mm_div_ps( d , e ) );

 

咋看之下,很多效率至上的人馬上就會大叫“昂貴的函數(shù)調(diào)用啊!Bad smell code!”。其實(shí)我正要告訴你,我也是效率至上派的。前面已經(jīng)說過了,這些看上去貌似函數(shù)的調(diào)用實(shí)際上并非函數(shù),而是所謂intrinsic,它們在編譯優(yōu)化中將被解釋為單條或多條SSE指令,而且編譯器會自動調(diào)節(jié)調(diào)用順序以使其最大并行效率。

不過除了直接使用這些intrinsic以外,我們還可以把它們封裝到類里面,重載運(yùn)算符,這樣就可以把運(yùn)算寫成可讀性更強(qiáng)的算術(shù)式。如果你不愿意自己動手封裝,也可以使用Intel封裝好了的F32vec4類,它提供了完備的運(yùn)算符重載,完全使用SSE,非常方便。

雖然Intel封裝好的類已經(jīng)很完善了,但還有一大堆數(shù)學(xué)運(yùn)算需要我們自己動手進(jìn)行編寫,如內(nèi)積(點(diǎn)積)和外積(叉積)。

 

首先來看一個比較實(shí)用的運(yùn)算,求倒數(shù)。求倒數(shù)在很多數(shù)學(xué)庫里都有專門的優(yōu)化,通常原理都是先求出一個近似值,然后通過Newton-Raphson逼近法求出較精確值,下面的代碼摘自NVfastmath.cpp:

 

#define FP_ONE_BITS 0x3F800000

// r = 1/p

#define FP_INV(r,p)                                                   \

{                                                                           \

    int _i = 2 * FP_ONE_BITS - *(int *)&(p);                  \

    r = *(float *)&_i;                                                \

    r = r * (2.0f - (p) * r);                                       \

}

 

而在SSE里也提供了兩條求倒數(shù)的指令rcpss/rcpps(對應(yīng)的intrinsic_mm_rcp_ss_mm_rcp_ps),不過這兩條指令求的并非是精確值,而是近似值,所以我們需要對它的結(jié)果進(jìn)行逼近處理。

 

float __rcp<float>( const float& a ) {

    register float r;

    __m128 rcp = _mm_load_ss( &a );

    rcp = _mm_rcp_ss( rcp );

    _mm_store_ss( &r , rcp );

    /* [2 * rcpps(x) - (x * rcpps(x) * rcpps(x))] */

    r = 2.0f * r - ( a * r * r );

    return r;

}

 

原理一致,只不過我們還可以用_mm_rcp_ps并行求四分量的倒數(shù)。如果你還對SSE的威力有所保留,那我建議你設(shè)計一個測試單元測試一下使用除法求倒數(shù)與使用SSE求倒數(shù),看效率到底是誰更高、高多少。當(dāng)然,我自己已經(jīng)測試過很多次了J

 

然后我們把注意力放到一條非常特殊的指令shufps(對應(yīng)intrinsic_mm_shuffle_ps)上面。這是一條非常有用的指令,它可以把兩個操作數(shù)的分量以特定的順序排列并賦予給目標(biāo)數(shù)。比如

 

__m128 b = _mm_shuffle_ps( a , a , 0 );

  

b 的所有分量都是 a 中下標(biāo)為0的分量。第三個參數(shù)控制分量分配,是一個8bit的常量,這個常量的1~8位分別控制了從兩個操作數(shù)中選擇分量的情況,具體怎么控制將在后面討論SSE匯編中一并說明,而在使用intrinsic的時候,最好使用_MM_SHUFFLE宏,它可以定義分配情況。下面我們來復(fù)習(xí)一下叉積的求法。

c = a x b

 

可以寫成:

 

Vector cross(const Vector& a , const Vector& b ) {

    return Vector(

        ( a[1] * b[2] - a[2] * b[1] ) ,

        ( a[2] * b[0] - a[0] * b[2] ) ,

        ( a[0] * b[1] - a[1] * b[0] ) );

}

 

那么寫成SSE intrinsic形式則是:

 

/* cross */

__m128 _mm_cross_ps( __m128 a , __m128 b ) {

    __m128 ea , eb;

    // set to a[1][2][0][3] , b[2][0][1][3]

    ea = _mm_shuffle_ps( a , a , _MM_SHUFFLE( 3 , 0 , 2 , 1 ) );

    eb = _mm_shuffle_ps( b , b , _MM_SHUFFLE( 3 , 1 , 0 , 2 ) );

    // multiply

    __m128 xa = _mm_mul_ps( ea , eb );

    // set to a[2][0][1][3] , b[1][2][0][3]

    a = _mm_shuffle_ps( a , a , _MM_SHUFFLE( 3 , 1 , 0 , 2 ) );

    b = _mm_shuffle_ps( b , b , _MM_SHUFFLE( 3 , 0 , 2 , 1 ) );

    // multiply

    __m128 xb = _mm_mul_ps( a , b );

    // subtract

    return _mm_sub_ps( xa , xb );

}

 

這就是shuffle強(qiáng)大的地方,它可以直接在寄存器里直接調(diào)整分量的順序。而且配合_mm_movehl_ps,我們可以輕松解決點(diǎn)積的運(yùn)算。_mm_movehl_ps把操作數(shù)高位兩個分量賦予目標(biāo)數(shù)的低位兩分量,而目標(biāo)數(shù)的高位兩分量值不變,相當(dāng)于:

 

a[0] = b[2];

a[1] = b[3];

 

三分量的向量求點(diǎn)積,可以寫成:

 

float dot( const float& a , const float& b ) const {

    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];

}

 

則用SSE intrinsic可以寫成:

 

/* x[0] * x[1] + y[0] * y[1] + z[0] * z[1] */

__m128 _mm_dot_ps( __m128 x , __m128 y ) {

    __m128 s , r;

    s = _mm_mul_ps( x , y );

    r = _mm_add_ss( s , _mm_movehl_ps( s , s ) );

    r = _mm_add_ss( r , _mm_shuffle_ps( r , r , 1 ) );

    return r;

}

 

通過這兩個例子,可以留意到向量內(nèi)元素的垂直相加一般形式,即:

 

/* x[0] + x[1] + x[2] + x[3] */

__m128 _mm_sum_ps( __m128 x ) {

    __m128 r;

    r = _mm_add_ps( x , _mm_movehl_ps( x , x ) );

    r = _mm_add_ss( r , _mm_shuffle_ps( r , r , 1 ) );

    return r;

}

 

那么通過擴(kuò)展,可以得到求向量長度的函數(shù),首先是求分量平方和函數(shù):

 

/* x[0] * x[0] + y[0] * y[0] + z[0] * z[0] */

__m128 _mm_square_ps( __m128 x ) {

    __m128 s , r;

    s = _mm_mul_ps( x , x );

    r = _mm_add_ss( s , _mm_movehl_ps( s , s ) );

    r = _mm_add_ss( r , _mm_shuffle_ps( r , r , 1 ) );

    return r;

}

 

然后就可以直接把結(jié)果求平方根,可得長度。解決了長度,接下來則是很重要的單位化了。可以說單位化是最重要的一個函數(shù),它經(jīng)常被調(diào)用到,而函數(shù)內(nèi)的陷阱卻又最多。求單位化其實(shí)并不難,就是分量除以向量長度,可以寫成:

 

void normalize( const Vector& a ) {

    float len = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];

    if( is_zero( len ) )

        return;

    len = 1 / len;

    a[0] *= len;

    a[1] *= len;

    a[2] *= len;

}

 

我和這個家伙打交道已經(jīng)有差不多七年時間了,所以脾性非常熟悉。首先求分量的平方和,判斷是否為0(問我為什么不直接用 if( len == 0 )?好樣的,請先去復(fù)習(xí)一下浮點(diǎn)數(shù)的基本知識),然后再求倒數(shù),最后反映到分量上。在把它寫成SSE intrinsic格式前,我先引入另外一個能極大提升運(yùn)算效率的函數(shù),求平方根的倒數(shù)。有數(shù)值運(yùn)算編成經(jīng)驗(yàn)的人都知道,如果說除法是惡魔的話,那么平方根就是撒旦了,而平方根的倒數(shù)簡直就是撒旦他媽。雖然上面提供了倒數(shù)的逼近方法,但僅僅使用它還是繞不開最主要的開銷、平方根運(yùn)算。幸好,SSE提供了一個直接計算平方根倒數(shù)近似值的指令,rsqrtss/rsqrtps(即_mm_rsqrt_ss_mm_rsqrt_ps)。照搬倒數(shù)求法,可以輕松得出:

 

/* r = 1 / sqrt(a) */

/* 0.5 * rsqrtss * (3 - x * rsqrtss(x) * rsqrtss(x)) */

__m128 _mm_rsqrt( __m128 a )

{

    / divisor

    static const __m128 _05 = _mm_set1_ps( 0.5f );

    static const __m128 _3 = _mm_set1_ps( 3.f );

    __m128 rsqrt = _mm_rsqrt_ss( a );

    rsqrt =

_mm_mul_ss(

_mm_mul_ss( _05 , rsqrt ) ,

_mm_sub_ss( _3 , _mm_mul_ss( a , _mm_mul_ss( rsqrt , rsqrt ) ) ) );

    return rsqrt;

}

 

那么就可以輕松得出單位化向量的函數(shù)了:

 

// normalize & return value

__m128 _mm_normalize( const __m128 a ) {

    // get length square

    __m128 l = _mm_square_ps( a );

    // test if length is zero

    if( _mm_iszero_ss( l ) )

        return z;

    // length inverse

    l = _mm_rsqrt( l );

    // shuffle

    l = _mm_shuffle_ps( l , l , 0 );

    // multiply to vector

    return _mm_mul_ps( a , l );

}

 

 

SSE除了以上這些數(shù)學(xué)運(yùn)算操作外,還提供了位運(yùn)算。位運(yùn)算?想到什么了嗎?對!比較與選擇。首先來看一個最簡單的,求絕對值。通常我們會把 abs 寫成非常簡潔的形式:

 

float abs( float a ) {

    a >= 0 ? a : -a;

}

 

但當(dāng)我們已經(jīng)Pack了一個向量到__m128結(jié)構(gòu)里,而又不希望Unpack他們進(jìn)行浮點(diǎn)數(shù)的比較,那么就可以使用SSE的位操作。

 

/* abs */

__m128 _mm_abs_ps( __m128 a )

{

    static const union { int i[4]; __m128 m; } __mm_abs_mask_cheat_ps

= {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};

    return _mm_and_ps( a, __mm_abs_mask_cheat_ps.m );

}

 

還記得單精度浮點(diǎn)數(shù)的符號存放在什么位上面嗎?我們只需把它除掉,然后就可以很輕松地得到了正值了。

 

圖形程序很多時候會用到32位浮點(diǎn)色彩,其值域通常為[0,1],所以clamp函數(shù)出現(xiàn)的頻率也十分頻繁。要將rgba的值同時clamp到值域內(nèi),毫無疑問,SSE的并行特性又得到了發(fā)揮的機(jī)會。先來看cut函數(shù),它負(fù)責(zé)把超出值域的值干掉,但為了更靈活,我們一次只cut一邊的區(qū)間,所以cut有兩兄弟,分別是locuthicut

 

__m128 _mm_locut_ps( __m128 val , __m128 bound )

{

    __m128 mask = _mm_cmplt_ps( val , bound );

    return _mm_or_ps( _mm_and_ps( mask , bound ) , _mm_andnot_ps( mask , val ) );

}

__m128 _mm_hicut_ps( __m128 val , __m128 bound )

{

    __m128 mask = _mm_cmpgt_ps( val , bound );

    return _mm_or_ps( _mm_and_ps( mask , bound ) , _mm_andnot_ps( mask , val ) );

}

 

_mm_cmp**_ps是一系列的比較函數(shù),非常豐富,也很好用,如果替換成相應(yīng)的if-else,并行性將被大大削弱。不過_mm_cmp**_ps的最大缺點(diǎn)就是靈活度不夠,返回值是一系列位標(biāo)記,其具體的用法將在SSE匯編中討論。有了這倆哥們,clamp變得非常簡單:

 

__m128 _mm_clamp_ps( __m128 val , __m128 min , __m128 max )

{

    return _mm_locut_ps( _mm_hicut_ps( val , max ) , min );

}

 

以上只是一些很簡單的實(shí)現(xiàn),利用了SSE intrinsic對數(shù)學(xué)運(yùn)算進(jìn)行優(yōu)化,并盡可能地不分拆向量,這樣可以保證8128位的xmm寄存器可以滿足大部分運(yùn)算。不過SSE intrinsic始終受編譯器生成代碼的質(zhì)量好壞影響,沒能真正發(fā)揮出SSE的全部威力,接下來我們將討論SSE匯編的用法與優(yōu)化。

 


to be continued...

posted on 2005-10-22 02:39 Chaos Chiao 閱讀(4722) 評論(7)  編輯 收藏 引用 所屬分類: Chaos on Graphics

評論

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2006-02-05 16:21 yyy
看了5遍,越看越好看!  回復(fù)  更多評論
  

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2006-04-25 03:22 信仔
請告之 現(xiàn)在做什么??

佩服!  回復(fù)  更多評論
  

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2006-04-25 19:39 丁勇
希望與博客主人及各位交流,科技創(chuàng)新,http://dycomputer.superbuckler.com/,或者http://blog.sina.com.cn/u/1224675400  回復(fù)  更多評論
  

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2006-04-25 19:44 晴天
2030就是歐美軟件外包專才培養(yǎng)計劃,http://www.i2030.org/  回復(fù)  更多評論
  

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2007-02-11 13:18 pb
寫的很好。謝謝分享。
不知道這個系列還有沒:)  回復(fù)  更多評論
  

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2008-04-04 20:19 Suzuki
i think there is practical significances only in 3D program. as for general program, vector is seldom used. nonetherless it is sound for boast. i wonder if there is hardware multiplier.  回復(fù)  更多評論
  

# re: Chaos on Graphics ~ About 數(shù)學(xué)庫之一 SSE/SSE2 2008-09-28 17:14 luguo
那么使用AMD的是否也有類似的指令來優(yōu)化
使用這些代碼在AMD上應(yīng)該不能運(yùn)行才對..  回復(fù)  更多評論
  


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国内成+人亚洲| 亚洲男人的天堂在线| 在线一区二区视频| 欧美在线free| 亚洲国产精品v| 亚洲神马久久| 久久亚洲精品一区| 国产精品久久激情| 1000部精品久久久久久久久| 亚洲性视频网站| 蜜臀久久99精品久久久久久9 | 久久成人资源| 欧美日本网站| 影音先锋久久久| 亚洲综合色视频| 欧美韩日一区二区| 午夜国产欧美理论在线播放| 欧美国产在线观看| 国内伊人久久久久久网站视频| 亚洲区第一页| 久久久久在线观看| 亚洲天堂av图片| 奶水喷射视频一区| 国产在线欧美日韩| 亚洲欧美精品中文字幕在线| 欧美激情精品久久久久久大尺度 | 国产一区二区0| 亚洲线精品一区二区三区八戒| 蜜桃精品久久久久久久免费影院| 亚洲午夜视频| 欧美日韩在线影院| 亚洲国产一区二区a毛片| 久久国产精品72免费观看| 日韩网站在线观看| 欧美成人精品三级在线观看| 黑人巨大精品欧美黑白配亚洲| 亚洲男人av电影| 亚洲免费成人av| 欧美国产精品一区| 亚洲第一中文字幕| 久久久蜜臀国产一区二区| 亚洲一区二区三区成人在线视频精品| 欧美激情精品久久久久久蜜臀| 1769国产精品| 久久综合九色综合久99| 亚洲欧美一区在线| 国产精品久久91| 中文亚洲视频在线| 亚洲人成网站精品片在线观看| 久久亚洲综合色| 好吊一区二区三区| 久久久久久黄| 欧美在线视频全部完| 国产色产综合产在线视频| 午夜在线视频观看日韩17c| 一区二区免费在线播放| 欧美日韩激情网| 夜夜爽99久久国产综合精品女不卡| 欧美福利一区| 欧美sm极限捆绑bd| 91久久久亚洲精品| 亚洲国产精品久久久久久女王| 乱人伦精品视频在线观看| 亚洲大胆人体视频| 欧美粗暴jizz性欧美20| 美女黄毛**国产精品啪啪| 亚洲国产女人aaa毛片在线| 欧美激情国产精品| 欧美电影打屁股sp| 一本到高清视频免费精品| 日韩视频一区二区三区| 欧美三级资源在线| 亚洲欧美日韩一区| 午夜精品一区二区三区电影天堂| 国产三级精品三级| 免费高清在线一区| 欧美 日韩 国产一区二区在线视频| 亚洲黄色视屏| 亚洲精品中文字幕在线| 欧美日韩一区自拍| 欧美亚洲综合另类| 久久精品视频导航| 亚洲福利视频在线| 亚洲日本一区二区| 国产精品久久久久毛片软件 | 久久精品综合| 久久久综合激的五月天| 亚洲精选视频免费看| 亚洲最黄网站| 国产乱肥老妇国产一区二| 久久久久国产免费免费| 久久视频在线看| 99re8这里有精品热视频免费| 99国产精品久久久久老师| 国产精品外国| 蜜桃久久av一区| 欧美日韩国产色站一区二区三区| 亚洲欧美偷拍卡通变态| 久久精品99国产精品| 亚洲精品久久嫩草网站秘色| 一区二区三区日韩| 黄色精品一区| 亚洲人成艺术| 国产日韩欧美麻豆| 亚洲国产欧美日韩另类综合| 欧美手机在线视频| 久久综合中文| 欧美日韩成人一区二区三区| 久久精品动漫| 欧美另类一区| 久久久另类综合| 欧美日韩视频第一区| 久久久另类综合| 欧美日韩伦理在线免费| 久久久国产精品一区二区中文| 欧美va天堂va视频va在线| 亚洲中午字幕| 蜜臀91精品一区二区三区| 香蕉成人啪国产精品视频综合网| 久久久久在线| 性伦欧美刺激片在线观看| 欧美aa国产视频| 久久高清国产| 欧美日韩视频在线一区二区观看视频 | 亚洲大片在线观看| 亚洲午夜久久久久久尤物| 亚洲国产欧美在线| 亚洲欧美日韩综合| 99精品视频免费观看| 久久国产加勒比精品无码| 亚洲私人黄色宅男| 欧美成人r级一区二区三区| 久久国产精品99精品国产| 欧美精品一区二区久久婷婷| 久久人人看视频| 国产精品毛片大码女人| 亚洲欧洲日本专区| 激情欧美一区二区| 亚洲一区二区三区高清| 一本色道久久综合亚洲91| 久久一区亚洲| 久久久久国产精品厨房| 国产精品黄色| 亚洲久久在线| 亚洲精品国产欧美| 久久午夜电影| 久久夜色精品国产欧美乱极品| 国产精品大片wwwwww| 亚洲精品你懂的| 激情综合亚洲| 欧美在线观看一区二区三区| 午夜精品国产精品大乳美女| 欧美区一区二区三区| 亚洲国产精品精华液网站| 伊人久久大香线| 久久国产福利| 久久九九久久九九| 国产伦精品一区二区三| 国产精品99久久久久久久女警 | 亚洲永久视频| 欧美日韩国产系列| 亚洲国产一区二区视频| 亚洲激情女人| 久久综合影视| 欧美 日韩 国产 一区| 尤物99国产成人精品视频| 欧美一区二区三区免费观看| 欧美在线观看视频一区二区| 国产精品女人毛片| 亚洲一区亚洲| 欧美一区高清| 国产三级精品三级| 欧美在线观看你懂的| 久久国产精品网站| 国产一区二区三区在线观看精品 | 精品成人一区二区| 久久久久久综合| 免费亚洲视频| 亚洲国产欧美一区二区三区久久 | 亚洲伦理在线观看| 欧美电影在线免费观看网站 | 欧美日韩在线视频一区二区| 亚洲精品你懂的| 99国产精品久久久| 欧美午夜寂寞影院| 亚洲午夜久久久久久久久电影网| 午夜精品网站| 国产亚洲欧美一区二区| 久久国产精品99精品国产| 另类亚洲自拍| 亚洲精品一区二区三区樱花| 欧美精品系列| 999亚洲国产精| 欧美一区二区高清| 国内精品久久久| 欧美99在线视频观看| 亚洲精品视频在线看| 小嫩嫩精品导航| 国模 一区 二区 三区| 久久久欧美一区二区|