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 על ידי:

הקוד הינו רלוונטי לכל סוגי ה shaders כלומר אין משתנה שמגדיר האם אנו עובדים עם ps , vs וכד .
דוגמא לשימוש בקוד הזה נמצאת ב DynamicShaderlinkageFX11 אשר ב Direct3d sdk
הדוגמא מראה לנו איך אפשר לשנות את סוגי התאורה על ה scene באמצעות שימוש ב dynamic linkage של shaders .
החלק שנוגע לתחקור הshader מתבצע בפונקציה
OnD3D11CreateDevice
אשר נמצאת בקובץ DynamicShaderLinkage11\DynamicShaderLinkage11.cpp
בדוגמא מודגם אפשרות של טעינה ושינוי דינמי של תהליך חישוב ה pixel shader באמצעות class ים שונים הממשיים class אבסטרקטי של חישוב מנת תאורה ל pixel .
כידוע חישוב מנת האור לpixel מורכב מכמה מרכיבים :
float3 Lighting = saturate( Ambient + Diffuse + Specular
עבור כל אחד מהרכיבים אפשר לחשב את המקדם של עוצמת האור בדרכים שונות בתלות בסיבוך של החישוב כמות ה resource ים שנדרשים וכד

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

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

ה 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
זאת מתבצע באמצעות :

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

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

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