سایه گذار
نوشته شده توسط : Mihayloo

یک سایه بان یک برنامه تعریف شده توسط کاربر است که برای اجرای در مرحله ای از یک پردازنده گرافیکی طراحی شده است. سایه بان ها کد را برای برخی از مراحل قابل برنامه ریزی خط لوله رندر ارائه می دهند. آنها همچنین می توانند به صورت کمی محدودتر برای محاسبات عمومی ، روی GPU استفاده شوند.

فهرست

مراحل

خط لوله رندر بخش های خاصی را برای برنامه ریزی تعریف می کند. هر یک از این بخش ها یا مراحل ، نوع خاصی از پردازش قابل برنامه ریزی را نشان می دهد. هر مرحله مجموعه ای از ورودی ها و خروجی ها را دارد که از مراحل قبلی و به مراحل بعدی منتقل می شوند (چه قابل برنامه ریزی یا نه).

سایه بان ها به زبان سایه بان OpenGL نوشته شده اند. خط لوله Rendering OpenGL مراحل سایه دار زیر را با نام ذکر کننده آنها تعریف می کند:

    : GL_VERTEX_SHADER و سایه بان ارزیابی: GL_TESS_CONTROL_SHADER و GL_TESS_EVALUATION_SHADER..(به GL 4. 3 یا ARB_COMPUTE_SHADER نیاز دارد)

یک شیء برنامه می تواند چندین مرحله سایه بان (ساخته شده از اشیاء Shader) را به یک کل و مرتبط با هم ترکیب کند. یک شیء خط لوله برنامه می تواند برنامه هایی را که شامل مراحل سایه بان فردی در یک خط لوله کامل است ، ترکیب کند.

در حالی که مراحل سایه بان از همان زبان استفاده می کند ، هر مرحله دارای مجموعه ای جداگانه از ورودی ها و خروجی ها و همچنین متغیرهای داخلی است. به همین ترتیب ، اشیاء سایه بان برای یک مرحله سایه دار خاص ساخته شده اند. بنابراین در حالی که اشیاء برنامه می توانند شامل چندین مرحله باشند ، اشیاء سایه بان فقط حاوی کد برای یک مرحله واحد هستند.

اعدام و دعوت ها

هنگامی که یک دستور ترسیم اجرا می شود ، شیء برنامه در حال حاضر محدود یا شیء خط لوله برنامه در عملیات ارائه استفاده می شود. بخش های قابل برنامه ریزی خط لوله رندر ، کد سایه دار ذخیره شده در برنامه (های) مورد استفاده در حال حاضر را اجرا می کنند.

هر مرحله سایه بان که دارای کد است ، یک یا چند بار بر اساس آنچه ارائه می شود اجرا می کند. هر مرحله سایه بان فرکانس اجرای آن را مشخص می کند.

هر اجرای یک مرحله سایه بان در یک دستور رندر "دعوت" نامیده می شود. با استثنائات نادر ، دعوت های مرحله سایه بان نمی توانند با یکدیگر تعامل داشته باشند. دقیقاً چه تعداد از دعوت ها برای بیشتر مراحل سایه بان اجرا می شود ، بستگی به میزان ارائه مطالب و ماهیت آن مرحله سایه بان دارد.

    : تقریباً یک بار در هر راس ورودی در جریان راس. در صورت استفاده از رندر فهرست بندی شده ، به دلیل حافظه نهان تبدیل شده ، این ممکن است کمتر از یک بار در هر راس باشد ، اما حداقل برای هر مجموعه منحصر به فرد از ویژگی های راس حداقل یک بار خواهد بود.: دقیقاً یک بار در هر راس خروجی در هر پچ. دعوت هایی که در همان وصله ورودی کار می کنند می توانند هر چند متغیرهای خروجی آنها ارتباط برقرار کنند.: تقریباً یک بار در هر راس در تساوی بخش انتزاعی. یک راس منحصر به فرد در پچ ممکن است بیش از یک بار پردازش شود. حداقل تعداد دعوت های TES یک بار در هر راس منحصر به فرد در پچ است. حداکثر یکی برای هر راس برای هر بدوی تولید شده توسط یک پچ است.: یک بار در هر ابتدایی رسیدن به این مرحله. هندسه سایه بان اجازه می دهد تا GS چندین بار برای هر ورودی بدوی فراخوانی شود.: یک بار در هر قطعه تولید شده توسط Rasterizer. این ممکن است بیش از این اجرا شود ، زیرا نمونه های سایه بان "یاور" ممکن است توسط اجرای آن استفاده شود. اما این موارد نمی توانند داده ها را بنویسند (به هر طریقی ، خواه خروجی های سایه بان قطعه ای ، فروشگاه بار تصویر یا هر چیز دیگری). آنها بیشتر برای محاسبه مشتقات ضمنی وجود دارند تا بسیاری از توابع نمونه برداری از بافت کار کنند.: تعداد دعوت ها توسط تعداد گروه های کاری درخواست شده توسط عملیات اعزام ضرب شده توسط اندازه محلی سایه دار محاسبات تعریف شده است. محاسبه دعوت های سایه بان در یک گروه کاری دارای برخی از قابلیت های ارتباطات محدود است.

مدل اعدام و واگرایی

بگذارید فرضیه یک واحد محاسباتی یک پردازنده یا GPU را به یک پردازنده فرمان و واحد ریاضی تقسیم کنیم (توجه داشته باشید که این بخش واقعاً صحیح نیست ، اما برای این بحث مفید است).

پردازنده فرمان وظیفه خواندن یک دستور و گفتن واحد ریاضی را دارد که چه کاری انجام دهد ، سپس خواندن دستور بعدی. اگر این دستور یک عملیات شعبه باشد ، این پردازنده فرمان است که به کجا می تواند شعبه کند ، انتخاب کنید که کدام دستور را برای اجرای بعدی انتخاب کنید. برای شاخه های مشروط ، فرمان را می توان به ریاضی تقسیم کرد که شرایط را محاسبه می کند (در واحد ریاضی اجرا می شود) ، و به دنبال آن پردازنده فرمان که نتیجه شرط را می خواند و دستور بعدی را برای اجرای آن انتخاب می کند.

یکی از مواردی که به GPU مزایای قابل توجه عملکرد خود نسبت به CPU می دهد این است که GPU ها قادر به انجام محاسبات بیشتر به صورت موازی هستند. اما مشخصات موازی سازی GPU با موضوعات CPU استاندارد کاملاً متفاوت است.

بیایید بگوییم که ما مجموعه ای از سکانس های فرمان را داریم که می خواهیم اجرا کنیم. هر دنباله مجموعه داده های ورودی خود را دارد و به مقادیر خروجی خاص خود می نویسد. اما هر دنباله فرمان کاملاً مستقل از یکدیگر است. هیچکدام از آنها به هیچ وجه نمی توانند با یکدیگر ارتباط برقرار کنند.

اگر می خواهید این مجموعه از دستورات را به طور موازی اجرا کنید ، برای هر دنباله فرمان به یک پردازنده فرمان و یک واحد ریاضی نیاز دارید.

با این حال ، بیایید سناریوی خود را تغییر دهیم. چه می شود اگر همه توالی های فرمان فوق در واقع همان دنباله دستورات باشند ، به سادگی بر روی مقادیر ورودی مختلف و نوشتن به مکانهای مختلف خروجی عمل می کنند؟اگر بخواهیم برای چنین عملیاتی یک پردازنده طراحی کنیم ، می تواند یک پردازنده فرمان واحد داشته باشد که چندین واحد ریاضی را تغذیه می کند. این یک دستور را می خواند و به واحدهای ریاضی می گوید که این دستور را در آن متغیرهای خود اجرا کنند. هر واحد ریاضی مقادیر موقت خود را نیز دارد تا به عنوان واسطه خدمت کند.

این همه کار می کنددرست تا زمانی که نیاز به اجرای یک شاخه مشروط (در صورت ، برای و غیره) داشته باشید. چه اتفاقی می افتد اگر محاسبات ریاضی که منجر به یک شاخه مشروط می شود ، مقادیر مختلفی را برای توالی های فرمان مختلف به دست آورد؟نتیجه مطلوب این خواهد بود که این سکانس ها دستورات مختلفی را اجرا کنند. اما ما فقط یک پردازنده فرمان داریم ، بنابراین نمی تواند دستورات مختلفی را برای اجرای آن انتخاب کند. چگونه با این کار مقابله می کنید؟

وقتی یک شاخه مشروط مانند این متفاوت می شود ، شما باید کاری ناخوشایند انجام دهید. این شاخه را می توان به مسیر A و مسیر B. تقسیم کرد. پردازنده فرمان اساساً مجبور است تمام واحدهای ریاضی را که برای اجرای دستورات مسیر B نیاز دارند ، مسدود کند. سپس مسیر A دستورات را اجرا می کند. پس از اتمام این کار ، به شعبه باز می گردد و دستورات مسیر B را اجرا می کند.

به این ترتیب ، در GPU های واقعی ، تعداد واحدهای ریاضی نسبت به تعداد فرآیندهای فرمان تمایل به نسبتاً کوچک نگه داشته می شود. 1 CP تا 32 MUS تقریباً به همان اندازه که ممکن است بخواهید بروید.

همچنین ، در GPU های واقعی ، واحدهای ریاضی واقعاً عناصر پردازش جداگانه نیستند. از این گذشته ، همه آنها قصد دارند همزمان همان دستور را اجرا کنند ، بنابراین آنها همان ریاضی را انجام می دهند ، فقط با ارزش های مختلف.

آنچه در GPU های واقعی اتفاق می افتد این است که شما یک "واحد ریاضی" دارید که می تواند همان عمل را بر روی چندین قطعه از داده های ورودی انجام دهد ، و به چندین مکان داده میانی می نویسد. یعنی اگر می خواهید x = 2 + 3 و y = 6 + 9 را انجام دهید ، از نظر مفهومی همان دستور را اجرا می کنید: علاوه بر این. بنابراین کاری که یک GPU انجام می دهد ، آنها را با هم جمع می کند. شما دو دستور اضافی جداگانه انجام نمی دهید. شما در حال انجام (x ، y) = (2 ، 3) + (6 ، 9) به عنوان یک عمل واحد هستید.

این جوهر دستورالعمل منفرد ، چندین داده (SIMD) است: یک دستورالعمل واحد که عملکرد خود را بر روی چندین قطعه مستقل از داده ها انجام می دهد.

براساس این مدل اجرای ، یک دعوت سایه دار فقط یکی از عناصری است که در یک سیستم پردازش SIMD اجرا می شود. به همین ترتیب ، چندین دعوت سایه دار در کنار هم قرار گرفته و در همان هسته SIMD اجرا می شوند.

مشکل بزرگ ، همانطور که در بالا ذکر شد ، واگرایی از انشعاب مشروط است. اما همه شاخه های مشروط یکسان نیستند. اساساً 2 نوع شاخه مشروط وجود دارد: آنهایی که می توانید در زمان کامپایل بگویید که آیا دعوت ها در همان SIMD هرگز واگرایی نخواهند کرد ، و مواردی که نمی توانید بگویید.

این کامپایلر فقط می تواند مطمئن باشد که در صورتی که عبارت ایجاد شاخه از ثابت ، مقادیر یکنواخت و سایر عبارات که خودشان فقط از ثابت و لباس حاصل می شوند ، در یک شاخه واگرایی وجود نخواهد داشت. ما می توانیم این را "بیان یکنواختی" بنامیم.

توجه داشته باشید که این با عبارات یکنواخت پویا متفاوت است. همه عبارات یکنواخت استاتیک نیز از نظر پویا یکنواخت هستند ، اما برعکس نیست. اگر یک مقدار غیر مستقیم یکنواخت در طول یک عمل سایه دار ثابت باشد (به عنوان مثال همه دعوت های سایه بان همان مقدار ورودی را دریافت می کنند) ، سپس عبارات بر اساس آن مقدار از نظر پویا یکنواخت هستند. اما از آنجا که کامپایلر نمی تواند این را بداند ، باید فرض کند که واگرایی امکان پذیر است.

بنابراین ، می توانید بیش از طیف وسیعی از مقادیر تعریف شده توسط یک متغیر یکنواخت با اطمینان کامل حلقه کنید که هیچ واگرایی وجود نخواهد داشت.

عبارات غیر یکنواخت ممکن است باعث واگرایی زمان اجرا شود. اما در GPU های مدرن ، آنها مسئله عملکرد را ایجاد نمی کنند ، مگر اینکه در زمان اجرا واگرایی کنند.

توجه: مقادیر ورودی خاصی وجود دارد که می توانید به طور معقول مشخص باشید که هیچ واگرایی رخ نخواهد داد. و Gl_DrawID یک مقدار ورودی است که از نظر یکنواخت یکنواخت است ، زیرا استاندارد به آن نیاز دارد که همیشه از نظر پویا یکنواخت باشد.

حتی با وجود شاخه های بالقوه واگرا ، کامپایلرها سعی می کنند در هر کجا که ممکن باشد از درد واگرایی اجرای واقعی جلوگیری کنند. به عنوان مثال ، یک ساده؟: بیان به ندرت باعث واگرایی سیما می شود. کامپایلر معمولاً کدی را تولید می کند که *هر دو عبارت *را ارزیابی می کند ، و هر یک از دعوت های فردی بر اساس شرایط ، یکی یا دیگری را دور می کند. اگر این عبارات شامل فراخوانی توابع پیچیده باشد ، کامپایلر ممکن است واگرایی واقعی را فراهم کند ، اما اگر ریاضی ساده مانند مقدار = شرط باشد؟x + 5: y - 20 ، کامپایلر تقریباً هر دو را اجرا می کند.

این بسته به اینکه کامپایلر چقدر هوشمندانه است ، به طور منظم در صورتی گسترش می یابد. اگر کد در آن شرایط بسیار کوچک باشد ، پس سعی خواهد کرد هر دو را در هر کجا ممکن اجرا کند. اما باز هم ، این کار فقط درصورتی انجام می شود که شرط قابل تعیین است که غیر واگرایی باشد.

محدودیت های منابع

سایه بان ها به منابع متنوعی دسترسی دارند. آنها می توانند به بافت ها ، لباس ها ، بلوک های یکنواخت ، متغیرهای تصویر ، پیشخوان های اتمی ، بافرهای ذخیره سازی سایه بان و اطلاعات دیگر دسترسی پیدا کنند. با این وجود دقیقاً در مورد چقدر چیزهایی که هر مرحله از سایه بان می تواند به آن دسترسی داشته باشد ، محدودیت هایی وجود دارد. هر منبع دارای حداکثر تعداد پرس و جو از منابع قابل دسترسی برای هر مرحله است.

توجه داشته باشید که هر مرحله ممکن است محدودیت هایی در منابع خاص مرحله داشته باشد. به عنوان مثال ، سایه بان های Vertex محدودیت سختی در تعداد ویژگی های راس دارند. در این بخش در مورد منابعی که برای همه سایه بان ها عمومی است ، بحث خواهد شد.

محدودیت های پرس و جو و معانی مرتبط با آنها به شرح زیر است. توجه داشته باشید که "*" نام صحنه است. این می تواند vertex ، tess_control ، tess_evaluation ، محاسبه ، هندسه یا قطعه باشد. این مقادیر همچنین دارای حداقل درخواست شده OpenGL هستند. اجرای OpenGL (از یک نسخه خاص) حداقل از این منابع پشتیبانی می کند.

MAX _*_ UNIFORM_COMPONTENTS این تعداد مؤلفه های فعال متغیرهای یکنواخت است که می توان در خارج از یک بلوک یکنواخت تعریف کرد. اصطلاح "مؤلفه" به عنوان مؤلفه اصلی یک بردار/ماتریس منظور شده است. بنابراین یک VEC3 3 مؤلفه را به خود اختصاص می دهد. حداقل مقدار در اینجا 1024 است ، اتاق کافی برای 256 VEC4 ثانیه است. GL_MAX _*_ UNIFORM_BLOCKS حداکثر تعداد بلوک های یکنواخت که این مرحله سایه بان می تواند به آن دسترسی پیدا کند. حداقل بازپرداخت OpenGL در GL 3. 3 و 14 در GL 4. 3 است. gl_max _*_ input_components حداکثر تعداد مؤلفه هایی که این مرحله می تواند به عنوان ورودی باشد. حداقل مقدار مورد نیاز با مرحله سایه بان به مرحله سایه بان متفاوت است. توجه داشته باشید که سایه بان های Vertex این مقدار را ندارند ، زیرا آنها از مکانیک ورودی متفاوت بر اساس ویژگی های راس استفاده می کنند. حد آنها gl_max_vertex_attributes است ، جایی که هر ویژگی می تواند حداکثر 4 مؤلفه باشد. gl_max _*_ output_components حداکثر تعداد مؤلفه هایی که این مرحله می تواند خروجی داشته باشد. حداقل مقدار مورد نیاز با مرحله سایه بان به مرحله سایه بان متفاوت است. توجه داشته باشید که سایه بان های قطعه ای این مقدار را ندارند ، زیرا آنها از مکانیک خروجی متفاوتی بر اساس بافرهای قرعه کشی استفاده می کنند. حد آنها gl_max_draw_buffers است ، جایی که هر خروجی بافر قرعه کشی می تواند حداکثر 4 مؤلفه باشد. GL_MAX _*_ TEXTURE_IMAGE_UNITS حداکثر تعداد واحدهای تصویر بافت که نمونه در این سایه بان می تواند به آن دسترسی پیدا کند. حداقل مقدار مورد نیاز OpenGL برای هر مرحله 16 است.

توجه: به دلایل میراث ، شمارشگر معادل سایه بان قطعه GL_MAX_TEXTURE_IMAGE_UNITS نامیده می شود. بدون "قطعه".

gl_max _*_ image_uniforms (نیاز به GL 4. 2/ARB_SHADER_IMAGE_LOAD_STORE) حداکثر تعداد متغیرهای تصویر برای این مرحله سایه بان است. حداقل بازپرداخت OpenGL برای سایه بان های قطعه و محاسبه 8 است و برای بقیه 0 است. این بدان معنی است که پیاده سازی ها ممکن است به شما امکان استفاده از متغیرهای تصویر را در مراحل غیر فریادی یا محاسبه ندهید. GL_MAX _*_ ATOMIC_COUNTERS (به GL 4. 2/ARB_SHADER_ATOMIC_COUNTERS نیاز دارد) حداکثر تعداد متغیرهای پیشخوان اتمی که این مرحله می تواند تعریف کند. حداقل بازپرداخت OpenGL برای سایه بان های قطعه و محاسبه 8 است و برای بقیه 0 است. gl_max _*_ atomic_counter_buffers (نیاز به GL 4. 2/ARB_SHADER_ATOMIC_COUNTERS) حداکثر تعداد بافر های مختلف است که متغیرهای پیشخوان اتمی می توانند از آن استفاده کنند. حداقل مورد درخواست OpenGL برای سایه بان های قطعه 1 ، 8 برای سایه بان های محاسباتی (توجه: مشخصات خاص TYPO) و دوباره 0 برای بقیه است. gl_max _*_ shader_storage_blocks (نیاز به GL 4. 3/ARB_SHADER_STORAGE_BUFFER_OBJECT) حداکثر تعداد بلوک های مختلف ذخیره سازی سایه دار است که یک مرحله می تواند از آن استفاده کند. برای سایه بان های قطعه و محاسبه ، حداقل درخواست شده OpenGL 8 است. برای بقیه ، 0 است.

محدودیت های کل

در حالی که اینها منابع قابل استفاده در مرحله سایه بان را تعریف می کنند ، محدوده هایی فراتر از این وجود دارد که در کل تمام مراحل سایه بان را پوشش می دهد.

gl_max_uniform_buffer_bindings محدودیت تعداد نقاط اتصال یکنواخت بافر. این حد برای GLBINDBUFFERRANGE هنگام استفاده از GL_UNIFORM_BUFFER است. در GL 3. 3 ، این مقدار حداقل 36 (3 مرحله سایه بان ، با حداقل 12 بلوک در هر مرحله) است. در 4. 3 ، این مقدار حداقل 72 است. gl_max_combined_uniform_blocks حداکثر تعداد بلوک های یکنواخت که همه برنامه های فعال می توانند از آن استفاده کنند. اگر دو مرحله (یا بیشتر) سایه بان از همان بلوک استفاده می کنند ، آنها به طور جداگانه به این حد حساب می شوند. در GL 3. 3 ، این 36 بود. در 4. 3 ، 70 است. GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS تعداد کل واحدهای بافتی که از همه برنامه های فعال قابل استفاده است. این حد در GLACTIVETEXTURE (GL_TEXTURE0 + I) و GLBINDSAMPLER است. در GL 3. 3 ، این 48 بود. در 4. 3 ، 96 است. gl_max_transform_feedback_separate_attribs هنگام انجام بازخورد تبدیل حالت جداگانه ، این حداکثر تعداد متغیرهای مختلف است که می توان ضبط کرد. این حداقل دارای حداقل 4 GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPENTS هنگام انجام بازخورد تبدیل حالت جداگانه است ، این حداکثر تعداد مؤلفه ها برای یک متغیر متفاوت است (توجه داشته باشید که می توان آرایه یا ساختاری را داشت) که می توانند اسیر شوند. این حداقل دارای 4 است. GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONTENTS هنگام انجام بازخورد تبدیل به ترانسفورماتور ، این تعداد کل مؤلفه هایی است که می توانند در یک بافر واحد ضبط شوند. این حداقل 64 است. GL_MAX_TRANSFORM_FEEDBACK_BUFFERS (به GL 4. 0/ARB_TRANSFORD_FEEDBACK3 نیاز دارد) حداکثر تعداد بافر که می توانند در عملیات بازخورد تبدیل شوند. این حداقل دارای 4 GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS (به GL 4. 2/ARB_SHADER_ATOMIC_COUNTERS) تعداد کل نقاط اتصال بافر پیشخوان اتمی است. این حد برای GLBINDBUFFERRANGE هنگام استفاده از gl_atomic_counter_buffer است. این مقدار حداقل 1. GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS (به GL 4. 2/ARB_SHADER_ATOMIC_COUNTERS) حداکثر تعداد متغیرهای بافر ضد اتمی در تمام برنامه های فعال است. این مقدار حداقل 1. GL_MAX_COMBINED_ATOMIC_COUNTERS (نیاز به GL 4. 2/ARB_SHADER_ATOMIC_COUNTERS) حداکثر تعداد متغیرهای پیشخوان اتمی در تمام برنامه های فعال دارد. این مقدار حداقل 8. GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS (نیاز به GL 4. 2/ARB_SHADER_ATOMIC_COUNTERS) تعداد کل نقاط اتصال بافر ذخیره سازی سایه بان دارد. این حد برای GLBINDBUFFERRANGE هنگام استفاده از GL_SHADER_STORAGE_BUFFER است. این مقدار حداقل 8 دارد.





:: بازدید از این مطلب : 68
|
امتیاز مطلب : 0
|
تعداد امتیازدهندگان : 0
|
مجموع امتیاز : 0
تاریخ انتشار : پنج شنبه 13 بهمن 1401 | نظرات ()
مطالب مرتبط با این پست
لیست
می توانید دیدگاه خود را بنویسید


نام
آدرس ایمیل
وب سایت/بلاگ
:) :( ;) :D
;)) :X :? :P
:* =(( :O };-
:B /:) =DD :S
-) :-(( :-| :-))
نظر خصوصی

 کد را وارد نمایید:

آپلود عکس دلخواه: