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

隨筆 - 505  文章 - 1034  trackbacks - 0
<2007年2月>
28293031123
45678910
11121314151617
18192021222324
25262728123
45678910


子曾經曰過:編程無他,唯手熟爾!

常用鏈接

留言簿(94)

隨筆分類(649)

隨筆檔案(505)

相冊

BCB

Crytek

  • crymod
  • Crytek's Offical Modding Portal

Game Industry

OGRE

other

Programmers

Qt

WOW Stuff

搜索

  •  

積分與排名

  • 積分 - 918854
  • 排名 - 14

最新隨筆

最新評論

閱讀排行榜

評論排行榜

“Batch, Batch, Batch:”
What Does It Really Mean?




這個看代碼里面batch相關的。

[Direct3D] 實現批次渲染、硬件 T&L 的渲染器和 D3DPipeline



在是否從 D3DRender 提供頂點緩存區操作給流水線時做了一些權衡,最后決定暫時使用 IDirect3DDevice9::DrawPrimitiveUP 來渲染,因為它更容易書寫,而且開銷是一次頂點拷貝,流水線也不用操心對緩存的使用。

D3DPipeline 并不是完整的,其涉及到從場景管理器中傳遞的靜態場景元素列表,這些元素需要事先被整理到各個子容器以便盡可能少地調整渲染狀態和寫頂點緩存。這些子容器由場景管理器維護,并在適當的時候調用 Render::DrawPrimitive 進行渲染。

大多數的 los-lib 結構與 D3DX 在內存上兼容的,在保持界面獨立的同時不影響性能。例如 los::blaze::Material 與 D3DMATERIAL 即是兼容的。燈光定義則存在差異,主要原因在于 los-lib 使用了各個獨立的燈光類型,而 D3DLIGHT9 則放置在統一的結構當中,當然,燈光對象通常并不在多個渲染狀態間改變,所以執行兩種燈光類型數據的轉換并不影響效率。一楨通常僅進行一次這樣的轉換。

另一個容易犯的錯誤在于幾何體法線列表的索引,法線為每個頂點索引設置獨立的值,而不再通過頂點列表的索引形式,嘗試使用頂點索引來查找法線將得到非預期的結果。


D3DRender:

   virtual int DrawPrimitive(const std::vector<VertexXYZ_N>& listVertex
        , 
const Matrix& matWorld, const Matrix& matView, const Matrix& matProj
        , 
const Material& material)
    {
        ptrDevice
->SetTransform(D3DTS_WORLD, (CONST D3DMATRIX*)&matWorld);
        ptrDevice
->SetTransform(D3DTS_VIEW, (CONST D3DMATRIX*)&matView);
        ptrDevice
->SetTransform(D3DTS_PROJECTION, (CONST D3DMATRIX*)&matProj);

        ptrDevice
->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL);
        ptrDevice
->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
        ptrDevice
->SetMaterial((CONST D3DMATERIAL9*)&material);

        
uint nPrim = (uint)listVertex.size() / 3;
        
uint nBatch = nPrim / _D3DCaps.MaxPrimitiveCount;
        
uint nByteBatch =_D3DCaps.MaxPrimitiveCount * (uint)sizeof(VertexXYZ_N) * 3;

        
for (uint idx = 0; idx < nBatch ; ++idx)
            ptrDevice
->DrawPrimitiveUP(D3DPT_TRIANGLELIST
            , _D3DCaps.MaxPrimitiveCount
            , 
&listVertex.front()
            
+ idx * nByteBatch
            , (
uint)sizeof(VertexXYZ_N));

        ptrDevice
->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nPrim % _D3DCaps.MaxPrimitiveCount
            , 
&listVertex.front()
            
+ nBatch * nByteBatch
            , (
uint)sizeof(VertexXYZ_N));

        
return 0;
    }

    
virtual int SetLights(const Lights& lights)
    {
        ptrDevice
->SetRenderState(D3DRS_AMBIENT
            , (lights.globalLight.GetColor()
            
* lights.globalLight.GetIntensity()).ToColor());

        
uint idxLight = 0;
        
for (size_t idx = 0; idx < lights.listPointLight.size(); ++idx)
        {
            
const PointLight& refLight = lights.listPointLight[idx];
            D3DLIGHT9 lght;
            ::memset(
&lght, 0sizeof(D3DLIGHT9));
            lght.Type 
= D3DLIGHT_POINT;
            lght.Range 
= refLight.GetDistance();
            lght.Attenuation1 
= 1.0f;

            Vector3 vPos 
= refLight.GetPosition();
            lght.Position.x 
= vPos.x;
            lght.Position.y 
= vPos.y;
            lght.Position.z 
= vPos.z;

            lght.Diffuse 
= lght.Specular
                
= *(D3DCOLORVALUE*)&(refLight.GetColor() * refLight.GetIntensity());

            ptrDevice
->SetLight(idxLight, &lght);
            ptrDevice
->LightEnable(idxLight++true);
        }

        
for (size_t idx = 0; idx < lights.listParallelLight.size(); ++idx)
        {
            
const ParallelLight& refLight = lights.listParallelLight[idx];
            D3DLIGHT9 lght;
            ::memset(
&lght, 0sizeof(D3DLIGHT9));
            lght.Type 
= D3DLIGHT_DIRECTIONAL;

            Vector3 vDir 
= refLight.GetDirection();
            lght.Direction.x 
= vDir.x;
            lght.Direction.y 
= vDir.y;
            lght.Direction.z 
= vDir.z;

            lght.Diffuse 
= lght.Specular
                
= *(D3DCOLORVALUE*)&(refLight.GetColor() * refLight.GetIntensity());

            ptrDevice
->SetLight(idxLight, &lght);
            ptrDevice
->LightEnable(idxLight++true);
        }

        
for (size_t idx = 0; idx < lights.listSpotLight.size(); ++idx)
        {
            
const SpotLight& refLight = lights.listSpotLight[idx];
            D3DLIGHT9 lght;
            ::memset(
&lght, 0sizeof(D3DLIGHT9));
            lght.Type 
= D3DLIGHT_SPOT;
            lght.Range 
= refLight.GetDistance();
            lght.Attenuation1 
= 1.0f;
            lght.Falloff 
= 1.0f;
            lght.Theta 
= refLight.GetHotspot().ToRadian();
            lght.Phi 
= refLight.GetFalloff().ToRadian();

            Vector3 vDir 
= refLight.GetDirection();
            lght.Direction.x 
= vDir.x;
            lght.Direction.y 
= vDir.y;
            lght.Direction.z 
= vDir.z;

            Vector3 vPos 
= refLight.GetPosition();
            lght.Position.x 
= vPos.x;
            lght.Position.y 
= vPos.y;
            lght.Position.z 
= vPos.z;

            lght.Diffuse 
= lght.Specular
                
= *(D3DCOLORVALUE*)&(refLight.GetColor() * refLight.GetIntensity());

            ptrDevice
->SetLight(idxLight, &lght);
            ptrDevice
->LightEnable(idxLight++true);
        }

        
return 0;
    }



D3DPipeline:

 virtual int ProcessingObject(const Object3D& object)
    {
        
++_DebugInfo.dynamic_object_counter;

        
const Model& refModel = object.GetModel();
        
const Vector3& pos = object.GetPosition();

        Matrix mat 
= object.GetTransform()
            
* object.GetOrientation().ObjectToInertial() * object.GetAxis()
            
* Matrix().BuildTranslation(pos.x, pos.y, pos.z);

        
for (size_t gidx = 0; gidx < refModel.listGeometry.size(); ++gidx)
        {
            
const Geometry& refGeom = refModel.listGeometry[gidx];
            
const Material& refMat = refModel.listMaterial[refGeom.indexMaterial];

            
//Triangle triangle;
            
//triangle.bitmap = (DeviceBitmap*)&refModel.listDeviceBitmap[refGeom.indexDeviceBitmap];

            std::vector
<VertexXYZ_N> listVertex;
            listVertex.reserve(refGeom.listIndex.size());

            
for (size_t iidx = 0; iidx < refGeom.listIndex.size(); iidx += 3)
            {
                
const Vector3& vertex0 = refGeom.listVertex[refGeom.listIndex[iidx]];
                
const Vector3& vertex1 = refGeom.listVertex[refGeom.listIndex[iidx + 1]];
                
const Vector3& vertex2 = refGeom.listVertex[refGeom.listIndex[iidx + 2]];

                Vector3 normal0 
= refGeom.listNormal[iidx];
                Vector3 normal1 
= refGeom.listNormal[iidx + 1];
                Vector3 normal2 
= refGeom.listNormal[iidx + 2];

                listVertex.push_back(VertexXYZ_N());
                VertexXYZ_N
& refV0 = listVertex.back();
                refV0.x 
= vertex0.x;
                refV0.y 
= vertex0.y;
                refV0.z 
= vertex0.z;
                refV0.normal_x 
= normal0.x;
                refV0.normal_y 
= normal0.y;
                refV0.normal_z 
= normal0.z;

                listVertex.push_back(VertexXYZ_N());
                VertexXYZ_N
& refV1 = listVertex.back();
                refV1.x 
= vertex1.x;
                refV1.y 
= vertex1.y;
                refV1.z 
= vertex1.z;
                refV1.normal_x 
= normal1.x;
                refV1.normal_y 
= normal1.y;
                refV1.normal_z 
= normal1.z;

                listVertex.push_back(VertexXYZ_N());
                VertexXYZ_N
& refV2 = listVertex.back();
                refV2.x 
= vertex2.x;
                refV2.y 
= vertex2.y;
                refV2.z 
= vertex2.z;
                refV2.normal_x 
= normal2.x;
                refV2.normal_y 
= normal2.y;
                refV2.normal_z 
= normal2.z;

                
++_DebugInfo.polygon_counter;
            }

            _PtrRender
->DrawPrimitive(listVertex, mat, _ViewMatrix, _PerspectiveMatrix, refMat);
        }

        
return 0;
    }
};


這篇看batching段。

Direct3D的一些小貼士收藏



GPU性能調試:

通常來說,使用CPU時間事件來調試GPU是低效并且是不準確的。D3D API在多數命令下會阻塞,甚至是Draw函數。它會在一些時間片上做一些真正的工作,而這往往是不可預知的。因此,GPU的性能調試只能用PIX或者是其他專用產品,例如NVIDIA’s NVPerfHUD來進行。

顯卡所用的內存:

顯卡所用的內存可以分為兩大類:本地的和非本地的(相對于顯卡來說)。在顯卡處理的某些數據類型的時候,需要本地內存,例如 幀緩沖。 非本地內存,有時也成為AGP卡槽內存(AGP aperture),可以被顯卡訪問的某些數據類型所在的系統內存,例如頂點緩沖。本地內存要比非本地內存快。

本地內存通常是在顯卡內的,但是有些顯卡可以共享系統內存,這通常是平衡速度和價格之間的選擇。在這種情況下,幀緩存可以存在于系統內存中,而不是在本地內存中。這種技術下,顯卡處理某些數據的速度比不使用共享內存的要慢,因為數據必須從I/O Bus(例如PCI-Express)上傳輸過來。但是這可以使顯卡成本大大降低。在NVIDIA,這種技術被稱為TurboCache,而ATI稱之為HyperMemory。

著色器和著色模型:

Shader是運行在GPU上的,處理一些D3D流水管線上一些任務的程序。有三種類型的shader,他們分別對應三種可編程的stage:

Vertex shader (頂點著色器VS) stage, geometry shader (幾何著色器GS) stage, 還有pixel shader(像素著色器PS) stage。其中幾何著色器只能在DX10平臺上使用。

著色模型(shader model)是在GPU上運行的虛擬機。每個虛擬機定義被稱為一種shader profile。并且包含了特定的匯編語言。

著色器的職責:

著色器通常是流水管線中描述物體表面的部分。例如,一種看起來像木頭的材質被稱為木頭著色器(wood shader)。而在D3D中,這些著色語言指令集可以做的事情遠不止描述物體表面。他們可以用來計算光照,矩陣轉換,頂點動畫,進行裁切,動態生成新的幾何物體,等等。在Mental ray中,shader按照職責可以劃分為surface shader, light shader, shader shader, output shader等等。

在D3D中,這三種著色器的職責劃分并不是很明確。例如,光照計算過可以在頂點著色器,或者是像素著色器中完成,這取決于應用程序的需求。因此,包含各種著色器的著色器集合應運而生。他們鏈接起來定義了一個工作流水線。

關于Direct3D 9 資源和內存類型:

D3D支持下列類型的資源:紋理(包括常規的和渲染目標render target),頂點緩沖,索引緩沖,字體,交換鏈(swap chain),狀態組,深度模板緩沖,特效等等。

有四種內存類型(池),資源可以在這里分配:

·         默認Default:在顯卡內存中,包括AGP卡槽內存和本地顯存。在設備丟失之后,必須被釋放,重構。

·         托管Managed:存在于系統內存中,按需拷貝到顯存。

·         系統SystemMem:永遠存在于系統內存中,并且不能直接用于渲染。可以當作源或者目標拷貝。例如UpdateSurface和UpdateTexture。

·         Scrach: 永遠存在于系統內存中,并且不會被設備大小或格式限制,例如紋理的2的冪限制。不能把它放到顯存中。

查找資源泄露:

在關閉一個基于D3D的應用程序時,D3D調試運行庫會報告內存泄露。按照以下步驟定位泄漏點。

1.       在DirectX Control Panel中(通常在DXSDK安裝目錄中可以找到),啟用“Use Debug Version of Direct3D 9”并且將Debug Output Level設置為”More”。確保Break on Memory Leaks被禁用。點擊Apply。

2.       在VS中調試運行應用程序。在關閉應用程序之后,查看VS的輸出窗口Direct 3D9: (WARN) : Memory Address:  00xxxxxx,  IAllocID= xx dwSize = xxxxxxxx;(pid = xxxxx)

3.       每條記錄對應了一個資源泄漏,查看并記住ID,然后在DirectX Control Panel中輸入ID并且點擊Apply。

4.       再次運行程序,重復以上步驟。程序會在分配點中斷,你可以檢查哪里遺忘釋放。

5.       當你調試完成之后,別忘了將Break On AllocID設置為0。

處理設備丟失(Device Lost)

一個D3D設備可以在很多情況下丟失,例如從全屏向窗口轉換,一個電源管理事件,按CTRL+DEL+ALT返回Windows Security Dialog。

必須采取措施去檢查一個設備是否丟失,丟失了之后如何恢復。

方法:在某些地方調用IDirect3DDevice9::TestCooperativeLevel,例如在每幀開始渲染之前調用。當發現設備丟失之后,采取下列措施:

1.       釋放所有在Default內存中的資源

2.       釋放其他沒有和Default, Managed, SystemMem綁定的資源

3.       調用IDirect3DDevice9::TestCooperativeLevel去確認設備是否可以被重置如果能,那么調用IDirect3DDevice9::Reset 如果不能,繼續等待,然后再嘗試

4.       重新創建需要的資源

渲染目標和交換鏈(Render Targets and Swap Chains)

一個渲染目標是一個用于保存在圖形流水線輸出像素的表面。也就是說,它是一個顏色數組。一個設備可以有一個或者多個活動的渲染目標,可以通過SetRenderTarget來啟用。一個用于渲染目標的表面只能放在Default池中,有三種渲染目標:

·         渲染目標表面Render target surfaces(通過CreateRenderTarget創建)

·         渲染目標紋理Render target textures(tongguo D3DUSAGE_RENDERTARGET標識來創建)

·         交換鏈Swap chains 交換鏈就是后備緩沖的集合,它們能夠相繼渲染到前緩沖,也就是屏幕上。一個在交換鏈中的后備緩沖可以當作一個渲染目標賦給一個設備。但是,不像其他的渲染目標,交換鏈可以渲染到屏幕上,因為交換鏈是和窗口/全屏大小綁定的。可以創建多個交換鏈,注意更改默認交換鏈大小會造成設備丟失,所以窗口程序會忽略默認的交換鏈,而使用一個附加的交換鏈來避免這個問題。渲染目標可以被鎖定(用來讀取),但是當這個渲染目標是活動的話,會影響系統性能。我們可以根據需要用IDirect3DDevice9::GetRenderTargetData來將一個在Default池中的渲染目標拷貝出來。可以使用IDirect3DDevice9::StrechRectangle在兩個在顯卡內存中的渲染目標中進行高效拷貝。

批處理(Batching)【重劍注:這個是重點

D3D的效率在很大程度上受制于傳給API的幾何模型數據的批次上。一個批處理就是調用一次DrawPrimitive或者DrawIndexPrimitive。在GPU可以處理數據前,CPU花相當長時間來處理每批數據。現在常見的CPU和GPU,可以參考以下數據:

·         使用DX9,CPU每秒可以處理50,000批次;使用DX10,這個數據是200,000。

·         在DX9中,處理2,000個三角形在CPU和GPU所花的時間大致相等。在DX10中,這個數據是500。簡單的著色程序使這個數字增加,復雜的著色程序使這個數字減少。在CPU和GPU在同一個批次上花相同時間的情況下,實例化(Instancing)可以提高三角形的輸出能力。因為以上原因,每個批次中處理數據的數量越大越好,這樣能夠將三角形的吞吐量最大化。

在實踐中,具體有兩種方式:

·         Consolidation合并:將相同性質的幾何元素合并起來,通常是將一些屬性進行排序的結果

·         Instancing實例化:將相同的幾何物體,經過一些細微的,不同的變換后畫出多個實例來。例如世界坐標系的轉換和顏色轉換。【重劍思考:Q:游戲里角色的護腕部位要同樣的模型,不能是一個護腕,一個手套,這個就是為了Instancing?A:非也!兩個護腕其實是一個模型,美術畫的時候就是畫了一對(左右各一個),中間就是斷開的】

頂點,索引緩沖Vertex / Index Buffer

頂點和索引緩沖有兩種類型:靜態和動態的。

一旦創建之后,靜態的緩沖使用起來比動態的快一倍。但是,動態緩沖的加鎖和解鎖要比靜態的快,它們是為更改的每一幀設計的,通常被存儲在AGP卡槽內存中。經常對靜態緩沖加解鎖是不明智的,因為只有等驅動完成了所有掛起的命令之后才能返回該緩沖的指針。如果經常這樣做,這會導致CPU和GPU很多不必要的同步,這樣性能將會變得很差。

為了得到最好的性能,必須采用動態緩存。這樣驅動可以繼續進行并行渲染。使用DISCARD或者是NOOVERWRITING標志可以實現這一點,這樣驅動可以在更新數據的同時繼續處理老的數據。

DISCARD:這個標志說明應用程序不關心當前緩沖的內容。所以在緩沖被渲染的同時,驅動可以給應用程序一個全新的緩沖。這個處理稱之為“buffer renaming”。注意,在實踐中,驅動傾向于不去釋放“緩沖重命名”中所用的內存,因此這個標志必須盡量少用。

NOOVERWRITE:這表示,對于之前添加的,不帶這個標志的數據,應用程序不會更改它。例如應用程序只會在現有緩沖之后添加數據。所以驅動可以繼續使用現有數據進行渲染。

CPU和GPU的并行處理

D3D runtime會將一堆命令做成命令串傳給GPU,這就允許GPU和CPU進行并行處理。這樣也是硬件加速渲染這么高效的原因之一。但是,在很多情況下,CPU和GPU必須進行同步之后才能做進一步的處理。通常來說,應該盡量避免這種情況,因為這會導致整個流水管線的刷新,大幅降低性能。例如,對靜態緩沖加鎖,這要求GPU先處理完所有的命令之后,才能返回被鎖緩沖的指針。如果用動態緩沖,就可以避免,就像前面講過的一樣。

有一些同步是不可避免的,例如,CPU可能會需要一些GPU還來不及處理的命令結果。在這種情況下,用戶會感到畫面延遲Lag。要避免這種情況,可以在GPU落后兩三幀的情況下調用Present來強迫CPU等待GPU。因此,調用Present可能比較慢,但是正式它處理了必要的同步。

狀態的更換State Changes

不管冗余還是不冗余,狀態的轉換在到達驅動層的時候,開銷總是很大。所以在某些層面,狀態轉換必須被過濾。一個對狀態進行更換的函數調用并不一定會開銷很大,因為D3D Runtime很有可能緩沖這些轉換請求,在真正調用DrawPrimitive函數之前不會去執行它。多次的狀態轉換也不會加大開銷,因為只使用最后一個狀態值。盡管如此,狀態轉換還是應該盡量避免。某些狀態轉換會比其他的轉換的開銷更大。例如,對于更改處于活動狀態的頂點緩沖和像素緩沖會導致整個流水管線的刷新。因為在某些顯卡上,同一時間每個類型只有一個著色器可以處于活動狀態。一個圖形流水線可以很長,花一段時間才能完成一個像素的渲染。因此,整個流水線的刷新需要盡量避免。在不同的顯卡上,某個狀態的更新的花費差別可能會很大。另外,D3D的函數調用個數也必須盡量的少,雖然它的開銷不如達到驅動層的狀態更改那么大。可以使用狀態塊來減少D3D API的調用,狀態塊可以將狀態的更改集中在一起,并且可以重用。


注意這段 3.3.4 Batching with the Geometry Instancing API

Inside Geometry Instancing(上)

Inside Geometry Instancing(下)



注意這個

GPU Gems 2  Chapter 3. Inside Geometry Instancing



3.5 References

Wloka, Matthias. 2003. "Batch, Batch, Batch: What Does It Really Mean?" Presentation at Game Developers Conference 2003. http://developer.nvidia.com/docs/IO/8230/BatchBatchBatch.pdf



看完這些,理解得差不多了。再結合現在的引擎代碼具體理解下。理解了才好辦事!
posted on 2009-09-23 17:58 七星重劍 閱讀(5472) 評論(2)  編輯 收藏 引用 所屬分類: Game Graphics

FeedBack:
# re: 理解D3D--(0)批次batch 2011-06-10 10:24 trcj
不錯;)  回復  更多評論
  
# re: 理解D3D--(0)批次batch 2011-10-30 15:47 ljb
不錯!繼續  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              亚洲高清在线精品| 亚洲激情在线播放| 欧美伊人久久| 欧美在线资源| 亚洲国产另类精品专区| 亚洲韩日在线| 欧美日韩理论| 欧美在线视频导航| 久久久亚洲成人| 日韩一级视频免费观看在线| 99v久久综合狠狠综合久久| 国产精品成人一区二区网站软件 | 久久精品国产免费| 久久成人免费| 一本久久综合亚洲鲁鲁五月天| 一本色道久久综合| 国户精品久久久久久久久久久不卡 | 黑人操亚洲美女惩罚| 欧美jjzz| 国产精品成人观看视频国产奇米| 久久精品成人一区二区三区| 久久综合九色| 亚洲欧洲av一区二区| 久久久久久尹人网香蕉| 亚洲一区二区三区四区在线观看 | 蜜臀久久久99精品久久久久久 | 国产精品久久久久一区二区三区| 久久午夜视频| 欧美性做爰毛片| 免费视频最近日韩| 欧美色综合网| 亚洲高清免费| 一区二区在线视频| 亚洲视频在线二区| 亚洲精品视频在线| 久久久国产精品一区二区三区| 亚洲无线一线二线三线区别av| 久久久夜色精品亚洲| 欧美一区激情视频在线观看| 欧美日韩国产在线| 欧美高清视频免费观看| 国产主播一区| 亚洲欧美三级伦理| 亚洲一区图片| 欧美日韩亚洲一区在线观看| 欧美成人一区二区三区片免费| 国产美女精品人人做人人爽| 一区二区高清视频在线观看| 亚洲卡通欧美制服中文| 久久久在线视频| 榴莲视频成人在线观看| 国产午夜精品一区二区三区视频 | 极品av少妇一区二区| 亚洲欧美日韩在线播放| 亚洲欧美日韩在线| 欧美午夜片欧美片在线观看| 亚洲美女在线国产| 99国内精品久久| 欧美日韩激情小视频| 最近中文字幕日韩精品 | 国产精品国产亚洲精品看不卡15 | 久久精品日韩| 国产一区自拍视频| 久久se精品一区二区| 久久久99爱| 精品动漫av| 狂野欧美一区| 亚洲第一在线| 一本色道**综合亚洲精品蜜桃冫| 欧美极品aⅴ影院| 亚洲精品日本| 久久久久久夜| 一二三四社区欧美黄| 欧美成年人视频网站欧美| 欧美肥婆在线| 99热在这里有精品免费| 欧美日韩国产123| 一级成人国产| 久久久久久久综合日本| 伊人久久综合97精品| 蜜桃精品久久久久久久免费影院| 91久久久国产精品| 亚洲欧美日韩在线播放| 狠狠入ady亚洲精品| 能在线观看的日韩av| 99re6这里只有精品视频在线观看 99re6这里只有精品 | 中国成人亚色综合网站| 欧美在线观看一区二区三区| 狠狠干成人综合网| 欧美成人免费大片| 亚洲网站在线观看| 欧美+日本+国产+在线a∨观看| 日韩午夜在线| 国内久久精品视频| 欧美日本韩国一区二区三区| 午夜亚洲一区| 亚洲精品你懂的| 亚洲欧美在线免费观看| 黄色精品一二区| 欧美午夜在线视频| 久久久久久网址| 亚洲视频在线观看网站| 欧美成人午夜剧场免费观看| 亚洲综合精品自拍| 91久久精品网| 国内精品久久久久国产盗摄免费观看完整版 | 美女性感视频久久久| 亚洲在线第一页| 亚洲七七久久综合桃花剧情介绍| 午夜视频久久久| 99视频精品全国免费| 国产亚洲成精品久久| 欧美jjzz| 久久久噜噜噜久久| 亚洲在线不卡| 99国产精品久久久| 亚洲电影免费观看高清完整版| 久久精品国产亚洲精品| 亚洲女女做受ⅹxx高潮| 日韩视频在线观看一区二区| 亚洲大片av| 黑人巨大精品欧美黑白配亚洲| 国产精品女人网站| 欧美日韩一视频区二区| 欧美成人免费在线| 久久亚洲精品网站| 欧美一区亚洲二区| 亚洲欧美成人在线| 亚洲一区自拍| 亚洲一区二区综合| 亚洲精品综合久久中文字幕| 欧美国产精品劲爆| 开心色5月久久精品| 久久久久国产精品麻豆ai换脸| 欧美一区久久| 欧美在线视频观看免费网站| 欧美亚洲系列| 欧美制服第一页| 久久久久久久尹人综合网亚洲| 性欧美videos另类喷潮| 亚洲在线视频网站| 亚洲大片精品永久免费| 午夜久久tv| 欧美一区精品| 久久久精品日韩欧美| 久久久久国产一区二区| 久久免费视频一区| 蜜桃av久久久亚洲精品| 欧美成人激情视频| 亚洲黄页一区| 一二三区精品福利视频| 亚洲校园激情| 欧美在线观看视频一区二区三区 | 亚洲人成亚洲人成在线观看| 亚洲精品美女久久久久| 一区二区三区国产在线| 亚洲欧美国产77777| 久久精品久久99精品久久| 久久综合网络一区二区| 欧美日本一区| 国产热re99久久6国产精品| 黑人巨大精品欧美一区二区小视频| 亚洲国产91| 亚洲永久视频| 久久综合给合| 日韩午夜三级在线| 午夜久久久久| 模特精品裸拍一区| 欧美午夜精品久久久久久久| 国内免费精品永久在线视频| 亚洲精品美女91| 欧美在线免费看| 亚洲电影免费在线观看| 亚洲性视频网站| 久热精品视频在线| 国产精品国产三级国产aⅴ浪潮 | 欧美在线亚洲一区| 欧美成人精品一区| 亚洲一区二区三区久久| 美日韩免费视频| 国产欧美精品日韩区二区麻豆天美| 在线成人中文字幕| 午夜精品偷拍| 亚洲精品男同| 噜噜噜久久亚洲精品国产品小说| 欧美天天影院| 亚洲精品一区二区三区av| 欧美一区午夜精品| 日韩视频免费在线| 久久频这里精品99香蕉| 国产精品美女在线观看| 亚洲精品男同| 米奇777超碰欧美日韩亚洲| 亚洲午夜未删减在线观看| 欧美成人久久| 亚洲国产精品久久久久婷婷884| 欧美亚洲综合在线| 在线亚洲欧美| 欧美三级视频在线| 亚洲伦伦在线|