View Full Version : دور زدن VertexDecleration توي Dx9
pswin.pooya
شنبه 14 خرداد 1390, 01:23 صبح
شايد خنده دار به نظر برسه اما راهي براي دور زدن VertexDeclerationها وجود داره:
رندرر من يه تابع براي رسم مشها به صورت زير داره:
Renderer::drawMesh(Mesh*,enum_t, uint_t lod);
خب حالا من ميتونم به راحتي مثلا براي رسم يه مش مشخص كنم كه چه اطلاعاتي بايد فرستاده بشه:
Renderer->drawMesh(m,DGE_POS | DGE_NORM,0);
بعدش تابع رسم مش من خودش با توجه به فلگها استريمها رو ست ميكنه و اونها رو ارسال ميكنه. اين مساله داخل OpenGL خيلي راحته و كافيه كه من فقط هندلر متغيير خودم رو داخل ورتكس شيدر و آفست VBO رو بدم تا كار رسم رو شروع كنه. اما خب رندرر DX من با اين شكل فرخواني مشكل داره و بايد Vertex Declaration مربوطه رو ست كنم و توي اين حالت بايد توي هر فراخواني يكي بسازم يا اينكه براي تمام حالتهاي ممكن يه Vertex Declaration بسازم كه اينكار كاملا غير منطقي هست و ... . نمي دونم بايد چي كار كنم راهي به نظر كسي ميرسه؟
- يه مورد ديگه:
من استريم هاي مختلفي براي انواع داده ها مثل نرمال و ورتكس و ... دارم و اونها رو دسته بندي نكردم مثلا توي shadow تنها ورتكس رو مي فرستدم و ديگه مثل nv يه استريم به اسم geometry تعريف نكردم. اينكار من درسته يا اشتباه؟ (من از مولتي استريمينگ استفاده ميكنم و هر استريم من با stride صفر و انديس متفاوت داخل vb ذخيره شده. مثلا به محض اينكه position ها تموم شدن نرمالها رو قرار دادم و ...)
hi.alir
شنبه 14 خرداد 1390, 09:58 صبح
اما خب رندرر DX من با اين شكل فرخواني مشكل داره و بايد Vertex Declaration مربوطه رو ست كنم و توي اين حالت بايد توي هر فراخواني يكي بسازم يا اينكه براي تمام حالتهاي ممكن يه Vertex Declaration بسازم كه اينكار كاملا غير منطقي هست
چرا باید تو هر فراخوانی یکی بسازید، خب دفعه اول یکی بسازید و باقی رو از همون استفاده کنید. این اطلاعات Vertex declaration نباید تو هر بار call کردن draw ارسال بشه که. یه متد createMesh بزارید و اونجا این اطلاعات رو دریافت کنید و مطابق با نیاز کاربر یکی بسازید. vertex declaration های کاربردی رو هم از قبل بسازید. مگه شما کلا تا الان از چند نوع vertex declaration استفاده کردید؟
pswin.pooya
شنبه 14 خرداد 1390, 10:28 صبح
چرا باید تو هر فراخوانی یکی بسازید، خب دفعه اول یکی بسازید و باقی رو از همون استفاده کنید. این اطلاعات Vertex declaration نباید تو هر بار call کردن draw ارسال بشه که. یه متد createMesh بزارید و اونجا این اطلاعات رو دریافت کنید و مطابق با نیاز کاربر یکی بسازید. vertex declaration های کاربردی رو هم از قبل بسازید. مگه شما کلا تا الان از چند نوع vertex declaration استفاده کردید؟
تابع drawMesh فقط كارش كشيدن مش با اطلاعات داده شده هست. مثلا ممكنه يه مش توي حالت استاتيك (با ورتكس شيدر استاتيك) نيازي به اطلاعات bone نداشته باشه يا زماني كه داره سايه اون رسم ميشه نيازي به اطلاعات ديگه به غير مكان نداشته باشه. اين اطلاعات ميتونن با توجه به نياز ورتكس شيدر تغيير كنن. اينكار توي OpenGL خيلي راحته و خوب هم جواب ميده (استفاده از فلگها و ارسال اونها) اما توي DX تبديل به يه مصيبت شده (من از كجا بدونم زمان اجرا يا استفاده كاربر شيدر اون چه نوع اطلاعاتي رو ميخواد كه بيام VertexDecleration اون رو بسازم). ايده اي كه به ذهنم رسيده اينه كه يه كلاس VertexDec بسازم و به جاي فلگها اون رو ارسال كنم اما اين موضوع باعث ميشه به پرفرمانس رندر GL يه مقدار كم لطمه وارد كنه (توي DX راحت يه مندلر ميگيره اما GL بايد تمام اينها رو دوباره از كلاس بخونه و ست كنه. يا اينكه بيام مثل nv تنها چهار نوع استريم تعريف كنم كه توي بدترين حالت تنها 4*3*2 تا حالت مختلف داشته باشم.
hi.alir
شنبه 14 خرداد 1390, 17:30 عصر
nv چیه؟
من از كجا بدونم زمان اجرا يا استفاده كاربر شيدر اون چه نوع اطلاعاتي رو ميخواد كه بيام VertexDecleration اون رو بسازممنظورم این بود که element های لازم رو از کاربر بگیرید بعد vertex declaration ش رو بسازید.
البته اگر درست یادم باشه D3D9 خودش فقط اطلاعاتی رو که نیاز هست میفرسته تو شیدر. مثلا اگر vertex shader فقط سمانتیک position0 رو بخواد، و vertex declaration بعلاوه ی position0، کلی چیز میز دیگه داشته باشه، اون ها رو ارسال نمی کنه. یعنی در واقع اصلا نیازی نیست که کاربر بگه می خوام چه چیز هایی فرستاده بشه. البته میگم درست یادم نیست، شاید عکس اینی که من گفتم بود، خودتون یه امتحان بکنید.
pswin.pooya
شنبه 14 خرداد 1390, 22:15 عصر
خب حالا كاري كه ميخوام بكنم اينه كه پرچمها رو از تابع drawMesh حذف كنم و براي هر شيدر راسي كه ايجاد ميشه با توجه به نياز اون يه vertex declaration بسازم. و زماني كه متريال رو ست ميكنم vertex declaration شيدر راس اون رو هم ست كنم. اما حالا يه مشكل ديگه دارم كه توي تاپيك زير مطرحش كردم:
http://barnamenevis.org/showthread.php?274836-%D9%85%D8%B4%DA%A9%D9%84-%D8%A8%D8%A7-%D8%B4%DB%8C%D8%AF%D8%B1%D9%87%D8%A7%DB%8C-HLSL&p=1275953&viewfull=1#post1275953
اين ايده به شرط اينكه بتونم ورودي هاي ورتكس شيدر رو تشخيص بدم به نظر خوب ميرسه. اما يه سوال ديگه:
داخل OpenGL يه آبجكت به اسم VAO هست كه RenderState رو داخل خودش نگهداري ميكنه (براي ورتكسها. مثلا از ديد دايركت: استريم ها و vertex declaration و همينطور vertex buffer رو ). حالا هر وقت كه بخواي مشي رو رسم كنه فقط كافيه يه بافر انديس رو ست كني و تابع draw رو صدا بزني اين شكلي با حداكثر سرعت ممكن تمام render stateها ست مشين و رسم انجام ميشه. ميخواستم بپرسم داخل دايركت همچين چيزي وجود داره. كه كلا سوئيچ كنم روي اين شيوه از شر vdecهاي خلاص بشم؟!!!
hi.alir
شنبه 14 خرداد 1390, 22:39 عصر
داخل OpenGL يه آبجكت به اسم VAO هست كه RenderState رو داخل خودش نگهداري ميكنه (براي ورتكسها. مثلا از ديد دايركت: استريم ها و vertex declaration و همينطور vertex buffer رو ). حالا هر وقت كه بخواي مشي رو رسم كنه فقط كافيه يه بافر انديس رو ست كني و تابع draw رو صدا بزني اين شكلي با حداكثر سرعت ممكن تمام render stateها ست مشين و رسم انجام ميشه. ميخواستم بپرسم داخل دايركت همچين چيزي وجود داره. كه كلا سوئيچ كنم روي اين شيوه از شر vdecهاي خلاص بشم؟!!!
درست نفهمیدم چی میگید. ولی اینکه از شر vdec خلاص بشید گمون نکنم.
pswin.pooya
شنبه 14 خرداد 1390, 23:49 عصر
توي OpenGL 3.0 به بعد يه چيزي به اسم VAO معرفي شد كه دفعه اول apple اون رو معرفي كرد بعدش توي 3 اومد توي هسته و توي OpenGL 3.1 تغييرات زيادي كرد كه حتي خود فونداسيون OpenGL هم گفت سعي كنيد ازش استفاده نكنيد. يه VAO موارد زير رو داخل خودش نگهداري ميكنه:
1. شماره vertex bufferاي كه بايد رسمش كنه. (توي OpenGL به جاي كلاسها از اعداد استفاده ميشه)
2. اشاره گرهاي وروديهاي ورتكس : تقريبا مثل استريمها داخل dx ميمونه
3. و يه چيزي تو مايه هاي Vertex Dec ي OpenGL نيازي به تعريف ورتكسها نداره (مخصوصا از ويرايش سه به بعد كه حتي لازم نيست كاربرد ورتكس رو مشخص كني)
خب حالا تنها كاري كه بايد بكني اينه كه هر وقت ميخواي رسم كني يه Index buffer ست كني و تابع glDrawElements رو فراخواني كني. ميتوني ايندكس بافر رو هم داخل VAO قرار بدي.
خب VAO هم خوبه و هم بد. مثلا فكر كن اگر 1000 تا مش داشته باشي بايد 1000 تا VAO بسازي چون VAO كار با بافرهاي راس مختلف رو نمي ده. از طرف ديگه چون همه چي رو نگه ميداره سوئيچ render state رو به حداقل ميروسونه (درايور بهينه ميكنه). يكي از علتهايي كه كار VAO نگرفتش همين موضوع ورتكس بافر بود.
نمي دونم داخل دايركت همچين مكانيزمي هست يا نه؟ فعلا تنها چيزي كه لازم دارم همون ورودي هاي شيدر راس هست و بس. اگر اونها رو بگيرم همه چي خود به خود حل مبشه.
hi.alir
یک شنبه 15 خرداد 1390, 00:16 صبح
راستش من زیاد بلد نیستم ولی اینی که میگید رو گمون نکنم بشه. تعریف کردن vdec هم واسه اینه که به DX بگیم Vertex shader مون چه چیز هایی داره (احتمالا). اون چیزی رو که گفتم امتحان کردید؟ اگر اونجوری باشه هم مشکلتون حل میشه.
سپول
یک شنبه 15 خرداد 1390, 14:02 عصر
باید یک manager درست کنید که حالت های مختلف ساختار ورتکس رو در خودش به صورت vert declaration نگه داره و بر اساس یک id یا همون FVF که بهش می دید vert declaration درست رو برگردونید
مثلا POS می شه یک vert declaration.
POS + NORMAL می شه یک declaration دیگه.
...
همه اینها رو هم می شه با برنامه نویسی درست کرد لازم نیست دونه دونه بسازید.
نکته دیگه اینکه شما مگه چندجور ساختار ورتکس دارید ؟ چون تازه همین manager که گفتم در multi-streaming کاربرد داره که بخواهید اطلاعات ورتکس رو بصورت runtime محدود کنید ... (مراجعه کنید به gpu gems 2) اگه حالت معمولی استفاده می کنید که اون هم نمی خواد کافیه برای هر ساختار ورتکس یک declaration تعریف کنید دیگه. شما در واقع برای هر ساختار ورتکس یک decl درست می کنید نه به ازای هر مش.
در ضمن ساختار direct3d پتانسیل بهتری به خاطر vertex decl داره (مخصوصاً در 10) چون با fvf دادن سرعت input assembler پایین میاد از اونجا باید اطلاعات ورودی رو مرتب کنه و فیلتر انجام بده بر اساس fvf. در حالی که با vertex declaration اطلاعات بصورت دقیق تعیین می شه و input assember دیگه محاسبات اضافی انجام نمی ده.
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.