DCSIMG
January 2012 - Posts - הבלוג של צביקה פאר

הבלוג של צביקה פאר

בבלוג זה אני אנסה לשתף את הקוראים בחקירת מגוון טכנולוגיות נפוצות פחות או יותר

January 2012 - Posts

Multithreaded Rendering DX11

ל Directx גירסה 11 נוסף פיצר חדש של Multithreading שמטרתו להפחית את העומס הרב על ה Rendering thread היחיד , על ידי פיזור של חלק מהעבודה שהוא עושה בthreads אחרים או שימוש בbatch ים של פקודות לgpu . בפוסט זה אני אנסה לשפוך אור על הפיצר הזה .

על אף ריבוי המעבדים ב GPU שמגיע לאלפים ,וריבוי ה Cpu ים במערכת. הפקודות ל GPU מה CPU עוברות דרך GPU Commands queue יחיד באופן סינכרוני.

ההזנה שלה Commands queue מתבצעת על ידי Thread יחיד בשם ה Rendering thread .

ניתן לראות ולדבאג את הפקודות הנכנסות ל Command queue באמצעות Pix

mtdx15

.

במצב שבו לא משתמשים ב Directx multitheading כל העבודה של הrendering מתבצעת בthread אחד .מכיוון שהעבודה של ה GPU הינה סנכרונית ל Rendering thread ,נוצרים מצבים שבהם הgpu מחכה בחוסר מעש לפקודות מה cpu.

 

טעינה אסינכרונית של Resource ים

טעינה של Reource ים כדוגמת Textures , Vertex buffersלוקחת זמן ,ביצוע טעינה ב Rendering thread גורם לעיקוב פעולת הGPU ,בד"כ במערכות מורכבות לא ניתן כמו ב Demos לטעון את כל הReource ים בתחילת התוכנית בשל העובדה שהכמות של הReources ים די גדולה  אלא יש לבצע את הטעינה של ה Reources ים On the fly  במהלך התוכנית .

Directx 11 מאפשר לנו ליצור את הResources ב Thread נפרד שונה מה Rendering thread

dx5

Multithreaded Submission

האפשרות לחלק את העבודה של ה Rendering של ה Device בין מספר threads .כל Thread בונה Display List שבסיום הבניה משוגר ל Rendering thread .

mtdx16

 

 

mtdx13

 

Per-Object Display Lists

יכולת זו מאפשרת להכין בthread שאיינו ה Rendering thread   ,אסופה של פקודות Draw שנקראות Display List המרכיבות אוביקט לוגי בSence כדוגמת החייל שמורכב מאוסף הDraws הבאים :

 

mtdx4

mtdx5

mtdx6

mtdx7

לאחר שיצרנו את הBatch אנו יכולים ב Rendering thread להשתמש בו על ידי קריאה ל Execute של אותו Display List

mtdx8

mtdx9

mtdx10

 

אחרי שה Display List נוצר הוא Immutable אין אפשרות לשנותו על ידי הוספה או גריעה של פקודות Draw .לדוגמא להוסיף לחייל חרב , לדמות פגיעות וכד .

ניתן לשנות את הResources שמשויכים לאותו DisplayList החל מדברים בסיסים כמו מטריצות העולם שבו החייל נמצא וכלה במטריצות הסיבוב המשויכות לBones של החייל שנועדו ליצור תנועה .

 

מימוש

עד לגירסה DX11 היה בDirectX רק Interface אחד כדוגמת IDirect3DDevice9 ששימש לפיקוד על ה DX device בDX11 הפיקוד על ה Device מתחלק ל 3 בעלי תפקידם שונים.

mtdx23

ID3D11Device – הinterface הזה יכול להיקרא מכל thread שהוא ולבצע טעינת reosurce וכד במקביל לפעולת הרינדור

Rendering thread ID3D11DeviceContext – הDevice context ששייך ל Renderingthread .אחראי להזרמת הCommands ל Command queue של כרטיס המסך .

Deffered Thread ID3D11DeviceContext – ה context שנוצר בthread שאיינו הrendering thread ויכול לבנות Display List .

mtdx91

בDirectx Sdk האחרון ישנו demo המדגים את הטכנולוגיה הזו .

mt1 

עבדות הrender כאן יכולה להתחלק למספר חלקים בילתי תלויים:

  • ציור ההשתקפות של ה scene במראות
  • ציור הצל 

הDemo בא להראות איך ניתן להשתמש ב Multithreaded rendering על מנת להגדיל את מספר ה fps .

(ניתן להריץ את הdemo בכמעט כל כרטיס שתומך ב dx11 ולראות את השיפור בביצועים )

הdemo מדגים 5 מצבים של Multithreaded rendering .

Immediate

מבצע רגיל בו thead  אחד מבצע את כל העבודה משמש referance

ST Def/scene

בmode זה סתם מדגים את השימוש בDeferrered context ללא כל יתרון של ביצועים

MT Def/scene

בMode זה חלוקה של עבודת הציור לפי נושאים כדוגמת רינודר הצל המראות כל אחד ל thread נפרד .

ST Def/chunk

בmode זה עבודת הציור מחולקת לchunks אשר כולם מבוצעים באופן סינכרוני מיועדלהראות את הapi של חלוקה ל chunks

MT Def/chunk

בmode זה עבודת הציור מחולקת לchunks ואז מתרחשת חלוקה של ה chunks לפי מספר המעבדים .

ניתן לראות לפי המונה של Frame per seconds אשר מראה עליה במספר ה frames שמרונדרים על ידי הכרטיס בהתאם למצבי ה Multi threaded rendering השונים בהתאם לכרטיס המסך ולמספר ה cpu ים במערכת .

הרבה פעמים נתקלתי בקוד review שעשיתי בעבודה כבדה של ה CPU כדוגמת חישוב אילו אוביקטים נמצאים ב view frustum או אפילו עבודות AI בRendering thread, הדבר נובע מזה שברוב ה Demos וגם בDXUT הקריאה ל OnFrameMove callback מתבצעת ב rendering thread .דבר זה גורם לפגיע באיכות הrendering ללא קשר ליכולות הgpu .

הצרכניה וRecoverability של אפליקציה

ביום שישי שעבר בשעה 9 בבוקר בדיוק שהתחלתי לפרוק את המוצרים מהעגלה למסוע של הקופאית בסופר התחילו המסופים של הקופות אחד אחרי השני לקרוס וקול הצווינג של קריאת הbar code נדם  .

הקופאיות ניסו לרסט את המסופים אבל זה לא עזר ,והתור והלחץ של הקונים (יום שישי יום קצר) התחילו לגעוש .

היחידים שנראו מבסוטים מכל העניין היו הקרפיונים שקיבלו חסד של עוד כמה שעות לפני שטוחנים אותם ושמים להם חתיכת גזר על העין .ביחד עם אותו סבאלה שהחליט לספר צ'יזבטים על אותם הימים בהם קנית במכולת חצי כיכר לחם והתווכחת איזה חצי יותר גדול .

מנהל הסופר ניסה להתקשר למרכז התמיכה ולתאר להם את הבעיה שהמקסימום מידע טכני שהוא יכל למסור לאותה מרכזנית זה הודעה הזויה של :Failed to login due to transaction abortion משהו כזה ,משהו שנראה לי שגם למפתח הראשי של האלפיקציה לא היה אומר הרבה .

האפשרות לבקש ממנהל הסופר לייצר קבצי minidump ולשלוח למרכז הבקרה לא היתה ראלית ,כמו כן להגיד למנהל הסופר שכעת שולחים לו קבצי symbols של הגרסה שמורצת אצלו שיוריד בבקשה מה msdn את ה windbg  ויתחיל לדבג את האפליקציה (זה טוב להדגמות עם תכוניות קטנות ).

גם האפשרות לכרוז ברמקול של הסופר :יש פה תכנת בקהל גם לא נראתה משהו. במיוחד אם היו מוצאים תכנתים בקהל הלקוחות סביר להניח שעזרה לא היו מקבלים מהם אלא עצות וחוות דעת על למה צריך לכתוב את כל האפליקציה מחדש , למה כדאי לעבור לענן , אנדרויד , mvc4 silverlight 5 או spring .

לא משנה כמות המוטיבזציה שהיו יוצרים אצל מנהל הסופר על ידי משפטים כדוגמת "עתיד הסופר בידך אין אף אחד מאחוריך!!! " האפשרות להמשיך את יום הקניות כסדרו תלויה עכשיו אך ורק ביכולות הrecoverability של האפליקציה !!

כמעט כל אפליקציה יכולה לקורס אם זה עקב בעיית חומרה או בעיית תוכנה ,אני יודע שבמטוסי נוסעים ישנם לפעמים מספר מחשבים לאותה משימה גיבוי אחד לשני ,אצלנו בסופר בנס ציונה לא נראה לי שזה המצב .

אינני יודע למה לפתע קרסו כל העמדות. יכול להיות שהארכיטקט של המערכת לא לקח בחשבון אפשרות של נתק בין ה clients ל servers , או אפשרות שה server יקרוס והמערכת לא תוכננה כOccasionally Connected Systems Architecture .

יכול להיות שהמערכת תוכננה כ Occasionally Connected Systems Architecture אבל הפצה של poison message לclient שאין נגדו הגנה גרמה לשיתוק של כל העמדות .

דוגמא ל poision message הינה עדכון של פרי חדש (ספוטה שחורה ) בטבלת התמונות של הפירות עם תמונה בגודל 0 שגורמת לexeption

imagesCAW504NL

(הספותה השחורה הינה פרי רעיל כל עוד איננה בשלה כשהיא בשלה ניתן לייצר ממנה עוגות שוקולד מדהימות).

מרחב המקורות ל Malfunction  במערכת client server של 24 קופות שכל הזמן מעדכנות נתונים בשרת וכל הזמן נדחף להם נתונים חדשים כגון מבצעים של יום שישי כמעט ולא יכול להיות אפס .

עם הזמן כמות המידע שנצברת ומשתנה במערכת גורמת למצבים שלא תוכננו כמו שאילת select בהצבה למשתנה שאמורה להחזיר רק ערך אחד מחזירה יותר ואז ה store procedure נופלת .בעיות של buffer overflow , בעיות של race condition שנוצר עקב שילוב של כמות מידע וכד .

בכל מקרה לפי דעתי על הארכיטקט של המערכת לתת את הדעת שמצב של קריסה לוקלית בעמדה אחת או כללית בכל העמדות אפשרי .

ישנו פיתרון build in  לחלק מסוים מהבעיות מנגנון ה Application Recovery and Restart ומנגנון הWindows Error Reporting   ניתן למצא עליו פרטים ב http://msdn.microsoft.com/en-us/library/cc303708.aspx  אבל הפתרון הינו חלקי ולא היה עונה על הבעיה שהתוכנה בקופות לא קרסה לא היה second chance exceptionהמערכת ברוב העמדות אפילו לא נתקעה אלא פשוט הפסיקה לעבוד לקבל barcodes .יכול להיות מצב שרק ה תת מנגנון של בחירת פירות לא עובד והמערכת בלתי שמישה לחלוטין.

Recoverability  היכולת של אפליקציה לעלות מחדש ולהמשיך לעבוד מהנקודה בה היא הפסיקה אחרי נפילה באג או תקיעה .(אם אוטומטית או על ידי מפעיל ).

ברמה של  product management יש מספר עקרונות לתמיכה ב Recoverability

1.זמן recovery ועליה מחדש מינימלי.במשך השעה הזו שהקופות לא פעלו עשרות עגלות של מוצרים ננטשו על ידי קונים ממורמרים כמובן שאין זמן ל production debugging וכד  .

2.אפשרות ניטור הבעיה – מיועד למקרים קיצוניים בהם restart של אפליקציה לא עוזר בד"כ כאשר הבעיה נגרמת על ידי מצב סטאטי כמו בעיית חומרה כגון HD מלא , או בעיית תוכנה מסוג של poison message.

אפשרות לפתוח חלון של קופאי בכיר המציג את הבעיה מגובה תמיד באפשרות לפתוח קובץ לוג באמצעות Notepad ולהבין משם מה הבעיה .

3.החזרת האפליקציה במדויק לstate הקודם

האפשרות שאחרי reset של עמדה יצטרכו להתחיל חשבון שהוא כבר לפני סיום מחדש איננה פיסבילית לחלוטין ,הרי המסוע של המוצרים לפני הקופה כבר מלא במוצרים של הלקוח הבא . בזמן ההמתנה הלקוחות על מנת ליצור לפחות תחושה של התקדמות הערימו ערמות על גבי ערמות של מוצרים על המסוע .להתחיל להחזיר את המוצרים ממסוע הקידמי לזה שלפני הקופה ,תוך כדי שלקוחות מפחדים שיחויבו פעמים …….

בכל מקרה צריך לשים לב שהיו מספר reset ים של האפליקציה לפני שהיא חזרה לעבוד , לכן איפוס של ה state ששמור לצרכי המשך עבודה אחרי כל עליה הינו שגיאה לוגית ,אחרי שהאפליקציה חזרה לסורה למשתמש צריכה להיות האופציה לבחור את ה state של ה Recovery המתאים לו מבין כל הsession הקודמים .

4.מנגנון שמירת ה Session צריך לתמוך במצב  שלאפשר לעבוד בעמדה אחרת במקרה ועמדה התקלקלה לגמרי.

5.אפשרות לעשות roll back למידע חדש שיכול לגרום לmulfunction יכול להיות שזה מידע ב cahce  בלוקלי או מידע שנמצא בשרת ואינו מאפשר למערכות להמשיך לעבוד .

עקרונות ארכיטקטונים לתוכנה שתיתמוך ב Recoverability

הפרדה בין state לפונקציונליות

מבחינה ארכיטקטונית על מנת לתמוך ב Recoverability של האפליקציה יש להקפיד על הפרדה בין state ל פונקציונליות .

state שמופרד מהלוגיקה יכול להישמר תדיר לצרכי recovery על ידי מגנוני הסיראליזציה הקיימים כמעט בכל השפות והטכנולוגיות לדוגמא:מנגנון ה pickle , shelve  בפיטון .

האויב הגדול ביותר של ההפרדה בין state לפקונציונליות זה מימוש לא נכון של class properties כלומר get accessor שמשנה את הstate של הclass ו Set Accessor של property אשר כאשר קוראים לו מספר פעמים עם אותו הערך הstate של ה class לא נשאר אותו הדבר .

שמירה מתמדת על ה state של ה אפליקציה לצרכי שיחזור המצב , הstate השמור לא צריך להיות רק חלק מה db של האפליקציה אלא גם כגיבוי חיצוני חיצוני כדוגמת קובץ או שימוש בNo sql db   מסוג document .

יכול להיות שהstate ששמור הינו מינימלי כגון שלב עריכת החשבון של לקוח , רוב הנתונים כבר נשמרו בdb

Recoverability1

 

 

תיכנון המערכת כ Occasionally Connected Systems Architecture

מערכת שתוכננה כ Occasionally Connected Systems Architecture על אף היותה בהרבה יותר מורכבת ממערכת שהינה client server פשוטה , הRecoverability שלה בהרבה יותר גבוהה ,יכול להיות מצב כמו בדוגמה שלנו שהשרת התקלקל אפשר היה לסיים בשקט את הפעילות תוך כדי שמירה של כל הפרטים לdb לוקלי אשר יסונכרן בoffline מתישהוא .

Recoverability2

 

 

logging

logging  נכון ומפורט נטול מידע בילתי רלוונטי ומידע מיותר שחוזר על עצמו כגון להפציץ את הלוג בהודעות מחזוריות תקינות .לא פעם נתקלתי בלוג של כמה גיגות מפוצץ בהודעות :Message was send או second chance exception occurred מבלי stack trace  .

והכי חביב זה הודעות wrong value ב default של switch case מבלי לציין מהו הworng value .

יכלותי לעביר סדנה של כמה חודשים עם כמות משחקי הניחושים ששיחקתי בחיי בזכות עצלות רגעית של מפתחים .

 

זמן עליה \ ירידה של המערכת סביר

לא צריך להטעין את כל המידע שבעולם ל cache בזמן עליית המערכת .אפשר לטעון מידע בJIT

כלי ניהול

רצוי שכל הניהול של האפליקציה המאפשרים בחינה של ה Log ו ניהול הdb (מחיקה של poision  messages  ) לא יהיו חלק מהאפליקציה לא של ה client  ולא של ה server

Ndis filter driver part 2

בפוסט הקודם דיברתי על מרחב הבעיה , פתרונות אפשריים ותאור הDriver בקליפת אגוז ,הפוסט הזה אני אמשיך וארחיב לגבי המימוש .

לאחר שהעתקנו אלינו את הדוגמא של הDriver מה DDK מ

C:\WinDDK\7600.16385.1\src\network\ndis\filter

קימפלנו את ה code  של Driver (עדיין עם build בסביבת command  כשאצלנו בחברה יוצאים לסרט לתכנתי הdrivers מקרינים במיוחד סרטים מהתקופה של הכלים בהם הם עובדים רק בשבוע שעבר היה זה מבצע באנטבה עם יורם גאון ואריק שני.  אנו מתאפקים עוד קצת עד שvisual studio 11 ישוחרר ותכנתי ה drivers יקפצו 30 שנה קדימה) 

והתקנו את ה filter driver או virtual machine או במחשב אחר .

(בVirtual machine יש להקפיד שהקונפיגורציה של הרשת תהייה חיבור מלא אחרת זה לא יעבוד  )

ההתקנה מאוד פשוטה מהNetwork connections .

network1

 

לאחר שהתקנו את ה driver  אנו רוצים לראות שאכן ה driver עובד והודעות שנשלחות לNIC אכן עוברות דרך ה Filter Driver שלנו .

הContainer של הודעות המידע (בשונה מהודעות הoid עליהן ארחיב פעם אחרת ) שעוברות ב Ndis drviers לסוגיו (אם זה בminiports , Filters ,protocols driverts etc' ) הינו struct מסוג Network buffers list .

מבנה ה Network buffer list

ndis2_7

 

הפרמטר של ה  NetBufferLists בcallbacks של :

SendNetBufferListsHandler,

ReturnNetBufferListsHandler,

SendNetBufferListsCompleteHandler

ReceiveNetBufferListsHandler

מורכב מ linked list של NET_BUFFER_LIST struct 

כל NetBufferList מצביע על struct של linked list of  NET_BUFFER

אשר מצביע על Strcut של MDL  linked list

כל MDL strcut מצביע על buffer של מידע .

על מנת להרגיש את הפעולה של ה filter יצרתי תוכנית קצרה ששולחת הודעת udp ,העדפתי udp כי כמות המידע שזורמת בהודעת udp קטנה בהרבה מזו של tcp אין צורך בתעבורת handshake וכד

בכוונה אני עוצר את התוכנית רגע לפני שליחת ההודעה על מנת להימנע לעצור ב breakpoints שנגרמים כתוצאה מביצוע פעולת GetHostEntery .

 

ndis2_6

 

לעניות דעתי כלי ה Debug של ndis שמוכלים ב Ndiskd.dll מאוד חזקים ומאפשרים ניתוח מהיר ופשוט של הן המידע והן הstack של ה ndis

http://msdn.microsoft.com/en-us/library/windows/hardware/ff552270(v=vs.85).aspx

אחרי שהתחברתי למחשב שמריץ את הfilter driver טענתי symbols והרצתי את תוכנית הבדיקה ,אני שם breakpoint בcallback של FilterSendNetBufferList

 

ndis2_4

מיד אחרי שליחת ההודעה אני נעצר ב breakpoint

 

 

ndis2_3

באמצאות כלי הdebug של ndis בחנתי את תוכן ההודעה .

פקודת ndiskd.nbl פורסת אוטומטית את הnbl בהינתן ה Address של ה nbl הראשון .

כפי שרואים באיור הבא ההודעה מורכבת משני mdl ים אחד מכיל את הheader של הודעת הudp והשני את הpayload של המידע ששלחנו .

 

 

ndis2_2

הNBL מכיל metadata נוסף כדוגמת ה SourceHandle המוצג באיור הבא ממנו ניתן ללמוד על מיקום ה driver שלנו בndis stack ואיך ה ndis stack  בנוי ומורכב .

 

 

ndis2_5

Direct3d11 Shader reflection interface

אחד השינויים המהותיים ב Direct3D11 הינו שהשימוש בקבצי  Effect המרכזים את כל ה shaders ואת ההגדרה של ה resources שshaders צריכים הוחלף  בשימוש בקבצים דיסקרטיים עבור כל shader כלומר שימוש בקבצים מופרדים עבור ה pixel shader , vertex shader ה shaders של ה tesselation ה geometry shaders וכד .

ההגדרה של technique שמכילה את כל הflow החל מהכניסה ל  graphic pipeline ועד ל הגדרות של הz-buffer הועברה מהeffect file לקוד של האפליקציה .

שינוי נוסף ב Direct3D11 הינו שהhlsl5 הפך להיות  Object orientedנוספה תמיכה  בinterfaces , ב ירושות ,

בדומה לאבולוציה של ++C מ C .(מעניין אם יום אחד נראה קוד hlsl דינמי סטייל python או php משהו כמו if ( !isset ($light)) die ();

אם בגירסות קודמות שלן directx  היינו יוצרים תצרותיות של הקוד על ידי שימוש ב if define  כעת  .hlsl5 נותן לנו את היכולת להגדיר class קונקרטי עבור כל טכניקה של רינדור .

מכיוון שיש decouple בין האפליקציה ל shaderים ניתן לשכלל את ה shader ים ולהרחיבם מבלי לשנות את האפליקציה , הם לא צריכים להיות חלק מתהליך הקומפילציה ובלבד שכל הresources מסופקים להם .

לעיתים נוצר צורך מצד האפליקציה לתחקר את ה shader הנטען על ידה לגבי איזה class ים הוא מכיל איזה interface ים הוא ממש ואיזה resource ים הוא מגדיר זאת על מנת שהאפליקציה תוכל להפעילו .

הדבר דומה ל  reflection ב net.

DX3D11 נותן לנו כלים לביצוע התחקור באמצעות מנגנון :Shader Reflection API אשר במרכזו נמצא com interface  :

ID3D11ShaderReflection

לאחר שטענו את ה shader אנו יכולים לקבל את ה Reference  ל ID3D11ShaderReflection על ידי:

code1

הקוד הינו רלוונטי לכל סוגי ה shaders כלומר אין משתנה שמגדיר האם אנו עובדים עם ps , vs וכד .

דוגמא לשימוש בקוד הזה נמצאת ב DynamicShaderlinkageFX11 אשר ב Direct3d sdk

Dynamic Shader Linkage 11 Sample

 

הדוגמא מראה לנו איך אפשר לשנות את סוגי התאורה על ה scene באמצעות שימוש ב dynamic linkage של shaders .

החלק שנוגע לתחקור הshader מתבצע בפונקציה

OnD3D11CreateDevice

אשר נמצאת בקובץ DynamicShaderLinkage11\DynamicShaderLinkage11.cpp

בדוגמא מודגם  אפשרות של טעינה ושינוי דינמי של  תהליך חישוב ה pixel shader באמצעות class ים שונים הממשיים class אבסטרקטי  של חישוב מנת תאורה ל pixel .

כידוע חישוב מנת האור לpixel מורכב מכמה מרכיבים :

float3 Lighting = saturate( Ambient + Diffuse + Specular

 

עבור כל אחד מהרכיבים אפשר לחשב את המקדם של עוצמת האור בדרכים שונות בתלות בסיבוך של החישוב כמות ה resource ים שנדרשים וכד

code2

 

כאן אחרי שדגמנו את ה texture אנו מכפילים את הערך בפונקציה וירטאולית :IlluminateAmbient

 

בדוגמא ניתנים שני מימושים שונים קונקרטיים ל IlluminateAmbient

אחד הפשוט :

code3

והשני מסתמך על

Hemispheres of light כלומר התחשבות גם של האור הישיר של השמים וגם האור שמוקרן מהאדמה

code4

ה shader מגדיר שני הטכנולוגיות לחישוב הAmbient light  בעוד האפליקציה צריכה לבחור עם איזה מימוש משתמשים .

האפליקציה צריכה למצא ב shader  את המשתנה שמחזיק את ה reference   ל class שממש את חישוב האור :abstractAmbientLighting ולהציב לתוכו את ה instance של ה class הנבחר.

 

שלבים בתחקור של ה shader בsample ובהצבה:

1.קבלת ID3D11ShaderReflection

2.שאילתה לגבי  כמות ה interface slots ב Shader

כלומר שאילתה באמצעות הפונקציה

pReflector->GetNumInterfaceSlots

שמחזירה את כמות ה interface pointers בshader

הסיבה לשאילתה הזו הקצאת  מערך של

ID3D11ClassInstance

שיכיל את כל הreference   ים ל class ים הקונקרטיים כמו כן נשתמש בערך הזה בהמשך כאשר נציב ל shader את מערך instance ים שבחרנו להשתמש בהם

3.עבור כל pointer ל interface ספציפי אני מעוניין לדעת את מיקומו היחסי ב shader

זאת מתבצע באמצעות :

code5

 

כעת עלינו לקבל מ הshader את ה instance עבור כל אחד מה class ים הקונקרטים :

code6

 

לקבוע עבור ה render את הps איתו הוא יעבוד ,כאשר הפרמטר השני מכיל את טבלת הinterface ים של ה class ים הקונקרטיים מסודרים לפי מספר ה slot אותם תחקרנו והפרמטר השלישי מכיל את גודל טבלת הclass ים הקונקרטיים .

code7

 

כמובן שאפשר לשחק עם ה shader במהלך תהליך ה render לחלקים שונים להפעיל class ים שונים ,דוגמא זו שהינה פשוטה קובעת את ה ps רק פעם אחת במהלך render ,ניתן כמובן לחלקים קרובים לקבוע pixel shader מורכב ויקר מבחינת צריכת משאבים ולחלקים רחוקים להשתמש ב ps יותר פשוט .

Ndis filter driver

באחד מהפרויקטים עליהם עבדתי לאחרונה היתה דרישה ליירט כל network packet  שנכנס או יוצא מהNIC (ללא כל קשר לאפליקציה המקבלת או שולחת אותו ) לחפש pattern מסוים באותו הpacket של רצף bytes מסויים ואם הpattern  מופיע לבצע באותו packet שינוי .

כמובן ששינוי ה packet מצריך חישוב מחדש של ה checksum בהתחשב בפרוטוקול של ההודעה הנשלחת .

שתי טכנולוגיות נשקלו על ידנו לטובת מימוש הדרישה :

WFP קיצור של Windows Filtering Platform שהינו פלטפורמה לירוט של תעבורת רשת ,שהינה זמינה החל מwindows vista . זו גם הטכנולוגיה המומלצת בכל פה על ידי אנשי מיקרוסופט כמו אולר שוויצרי לצרכים כאילו .

NDIS filter driver שהינה סוג של kernel driver שמשמ לירוט ושינוי של תעבורת רשת.

אל אף היתרון הגדול של wfp המאפשר עבודה בuser mode  בחרנו לממש את הדרישה כNDIS filter driver . וזאת מכמה סיבות בהן:

גמישות –NDIS filter drivers  חושפים יכולות אשר WFP לא חושף לדוגמא אפשרות לעבד OID requests

מבחינת פשטות של קידוד הפתרון יותר פשוט לכתוב NDIS Filter driver  מאשר WFP .המבנה של אפליקצית wfp יותר מסובך מndis filter driver .

מכיוון שיש לנו בקבוצה יותר ניסיון בכתיבת ותחזוקת  NDIS drivers מאשר ב WFP .

כמו כן ישנה דוגמא שהינה השלד של ה פתרון שלנו בWindows driver kit ורוב הדוגמאות שמצאנו של WFP היו בנושא של inspection של packets  ופילטור של packets ולא של שינוי.

בניגוד לחלק מהקטגוריות של wdm drivers  ,דיבאגינג והרצה של NDIS drivers ניתן לעשות בvirtual  machine דבר שמקל מאוד את הפיתוח .

הדוגמא שיצאנו ממנה הינה :NDISLWF.SYS אשר נמצאת בnetwork\ndis\filter שהינה דוגמא של ndis 6.0 filter driver .

פעולות ההכנה שביצענו בדוגמא היו :

1.הוספת תמיכה ב tracing באמצאות wpp חשבנו על האפשרות של תמיכה מלאה ב etw  עם אפשרות של יכולות לשאילתות לגבי מספר ה packets  ששונו , יחסית למספר הpackets  שהתקבלו וכד אבל נראה כי לא היה לזה צורך מבחינת הנדסת המוצר ומכיוון שהוספת תמיכה בetw בהרבה יותר מורכבת מאשר wpp ,הסתפקנו בwpp .

מכיוון שעבודה עם virtual machine לצורך פיתוח dirvers לא רואים את ה output של DbgPrint החלפנו את כל הקריאות של DbgPrint ב DoTraceMessage של ה Wpp

2.הוספת תמיכה ב kmdf שזה nice to have וממש לא must .

המרחב הטריטוריאלי של הFilter driver בndis stack נמצא בין ה miniport adapter ל protocol driver כלומר המידע שמגיע עליו הינו מידע גולמי ישר מהNIC או row data שצריך להישלח לndis ,אין לנו בזמן העיבוד אינדיקציה לגבי הprotocol של ההודעה אבל אנו יודעים שהתשתית איננו מערבבת בין הודעות כלומר לא תגיע חצי הודעה או שתי הודעות באותה קריאה .

 

IC506632

הapi של מימוש ה driver מבוסס על פקודות מספריית הndis .

המבנה של ה Ndis filter driver הינו מאוד פשוט ומבוסס על רישום להודעות callback של התשתית.רישום לחלק מההודעות הינו חובה ולחלקן כאופציה . בסיום הטיפול בcallback הdriver צריך לקרא לפקודת ndis שמזרימה את ההודעה ל filter driver הבאה בתור.

כך שהpattern של ה driver נראה כ Observable pattern בשילוב עם chain of responsibility.

במהלך הביצוע של הDriverEntery ה Driver מבצע רושם את עצמו כ Ndis filter driver באמצעות קריאה לNdisFRegisterFilterDriver.

NdisFRegisterFilterDriver מקבל כפרמטר את הstruct של

NDIS_FILTER_DRIVER_CHARACTERISTICS שמכיל את הpointers ל callbacks של NDIS לדוגמא :

SendNetBufferListsHandler נקרא עבור  הודעות שנשלחות ל nic .

הcallback של SendNetBufferListsHandler מכיל referance ל NBL שמכיל את ה row data שנשלח בצורה של network buffer list .

בסיום עיבוד המידע הdriver חייב לקרא ל NdisMSendNetBufferListsComplete על מנת להמשיך את דרכו של ה NBL לעבר ה Miniport adapter של ה ndis

בישום שלנו היינו צריכים רק לשנות את ה payload בתנאים מסוימים כך שכל הודעה שהתקבלה ב callback אחרי עיבדו סינכרוני של המידע מיד המשכנו את התהליך על ידי קריאה ל NdisMSendNetBufferListsComplete ,יחד עם זאת ניתן לעבד את המידע אסינכרונית לקבוץ ולהפריד הודעות (חשוב להקפיד על הסדר של השליחה מהcallback).

 

הישום שלנו ממש את הטיפול ב SendNetBufferListsHandler   בצורה הבאה

 

 

Drawing2

 

בפוסטים הבאים אני אפרט את המימוש של ה filter לעומק.