<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Seongcheol Jeon</title>
    <description>The latest articles on DEV Community by Seongcheol Jeon (@seongcheoljeon).</description>
    <link>https://dev.to/seongcheoljeon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3418479%2Fded5efc4-b614-4bdf-8fb7-65da3f172ca2.jpeg</url>
      <title>DEV Community: Seongcheol Jeon</title>
      <link>https://dev.to/seongcheoljeon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seongcheoljeon"/>
    <language>en</language>
    <item>
      <title>[⭐] Wise Saying</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Sat, 17 Jan 2026 10:54:49 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/wise-saying-27kn</link>
      <guid>https://dev.to/seongcheoljeon/wise-saying-27kn</guid>
      <description>&lt;p&gt;남의 일에 관심 많고, 남의 시선에 흔들리고, 자신이 아닌 남을 살아가는 먼지 앉은 눈빛으로는 세상의 절박한 그 무엇에도 말을 걸 수가 없다. &lt;br&gt;
우리가 자기를 들여다보지 않아서 우리 눈빛을 잃은 것처럼, 이 세상이 이토록 불안한 구조로 가는 것은 우리가 그토록 서로의 삶을 훼손했기 때문이다.&lt;br&gt;
좋은 눈빛에 흔들렸으면 한다. 그것이 살아가는 것이다. 쉬지 않는 눈빛과 마주쳤으면 한다. 그것이 다행한 일이다.&lt;/p&gt;




&lt;p&gt;"인간에게서 가장 놀라운 점이 무엇인가요?"&lt;/p&gt;

&lt;p&gt;신이 대답했다.&lt;/p&gt;

&lt;p&gt;돈 벌기 위해 건강 잃어버리는 것.&lt;br&gt;
그리고는 건강 되찾기 위해 돈 잃는 것.&lt;/p&gt;

&lt;p&gt;미래 염려하느라&lt;br&gt;
현재 놓쳐버리는 것.&lt;br&gt;
그리하여 &lt;br&gt;
현재도 미래도 살지 못하는 것.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>[C++] const 키워드와 반복자</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Mon, 29 Dec 2025 17:16:03 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/c-const-kiweodeuwa-banbogja-4pee</link>
      <guid>https://dev.to/seongcheoljeon/c-const-kiweodeuwa-banbogja-4pee</guid>
      <description>&lt;ul&gt;
&lt;li&gt;vector::iterator&lt;/li&gt;
&lt;li&gt;vector::const_iterator&lt;/li&gt;
&lt;li&gt;const vector::iterator&lt;/li&gt;
&lt;li&gt;const vector::const_iterator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;위의 반복자들을 비교 설명한다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;iterator&lt;/span&gt; &lt;span class="n"&gt;iter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// iter는 p처럼 동작&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;const_iterator&lt;/span&gt; &lt;span class="n"&gt;citer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// citer는 cp처럼 동작&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;citer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;iterator&lt;/span&gt; &lt;span class="n"&gt;iter_const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// iter_const는 p_const처럼 동작&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;p_const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;iter_const&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p_const&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;const_iterator&lt;/span&gt; &lt;span class="n"&gt;citer_const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// citer_const는 cp_const처럼 동작&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;cp_const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;citer_const&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cp_const&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;vector::iterator iter;

&lt;ul&gt;
&lt;li&gt;iter는 다음 원소로 이동 가능하고 원소의 변경이 가능한 반복자이다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;vector::const_iterator citer;

&lt;ul&gt;
&lt;li&gt;citer는 다음 원소로 이동 가능하고 원소의 변경이 불가능한 반복자이다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;const vector::iterator iter_const;

&lt;ul&gt;
&lt;li&gt;iter_const는 다음 원소로 이동이 불가능하고 원소의 변경이 가능한 반복자이다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;const vector::const_iterator citer_const;

&lt;ul&gt;
&lt;li&gt;citer_const는 다음 원소로 이동이 불가능하며 원소의 변경이 불가능한 반복자이다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;포인터와 연결해 보면, 어렵지 않게 이해할 수 있다. 사실 &lt;code&gt;iterator&lt;/code&gt;와 &lt;code&gt;const_iterator&lt;/code&gt;만을 주로 사용하므로 이 두 반복자만 알고 있어도 된다.&lt;/p&gt;

</description>
      <category>cpp</category>
    </item>
    <item>
      <title>[C++] std::forward</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Tue, 28 Oct 2025 05:35:41 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/c-stdforward-2l48</link>
      <guid>https://dev.to/seongcheoljeon/c-stdforward-2l48</guid>
      <description>&lt;p&gt;&lt;code&gt;forward&lt;/code&gt;는 &lt;code&gt;&amp;lt;utility&amp;gt;&lt;/code&gt; 헤더에 정의되어 있다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;remove_reference_t&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;noexcept&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// (1)&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;remove_reference_t&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;noexcept&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// (2)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;(1)&lt;/code&gt; 오버로딩의 경우, &lt;em&gt;lvalue&lt;/em&gt;를 &lt;code&gt;T&lt;/code&gt;에 따라 &lt;em&gt;lvalue&lt;/em&gt; 혹은 &lt;em&gt;rvalue&lt;/em&gt;로 전달한다.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[UE] Render Dependency Graph (RDG)</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Fri, 24 Oct 2025 05:13:34 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/render-dependency-graph-rdg-m50</link>
      <guid>https://dev.to/seongcheoljeon/render-dependency-graph-rdg-m50</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;RDG를 더욱 이해할 수 있도록 &lt;a href="https://dev.epicgames.com/documentation/en-us/unreal-engine/render-dependency-graph-in-unreal-engine" rel="noopener noreferrer"&gt;UnrealEngine 문서&lt;/a&gt;를 Clone 및 정리하여 작성하는 글이다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  렌더 종속성 그래프 (Render Denpendency Graph, RDG)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;RDG란, 렌더 명령을 컴파일하고 실행할 수 있도록 그래프 데이터 구조체로 기록하는 즉시 모드 API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;렌더 그래프 또는 RDG라고도 하는 &lt;strong&gt;렌더 종속성 그래프(Render Dependency Graph)&lt;/strong&gt;는 렌더 명령을 컴파일하고 실행할 수 있도록 그래프 데이터 구조체로 기록하는 즉시 모드 어플리케이션 프로그래밍 인터페이스(API)이다. &lt;br&gt;
&lt;code&gt;RDG&lt;/code&gt;는 오류에 취약한 연산을 &lt;strong&gt;자동화&lt;/strong&gt;하여 고수준 렌더링 코드를 &lt;strong&gt;단순화&lt;/strong&gt;하며, 그래프를 탐색해 메모리 사용을 &lt;strong&gt;최적화&lt;/strong&gt;하고 &lt;code&gt;CPU&lt;/code&gt;와 &lt;code&gt;GPU&lt;/code&gt;의 렌더 패스를 *&lt;em&gt;병렬화&lt;/em&gt;한다.&lt;/p&gt;

&lt;p&gt;RDG의 대표적인 기능은 아래와 같다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;비동기 컴퓨트 펜스 예약&lt;/li&gt;
&lt;li&gt;최적의 수명과 메모리 Aliasing을 통한 일시적 리소스 할당&lt;/li&gt;
&lt;li&gt;분할 베리어를 사용한 서브리소스 전환으로 레이턴시를 숨기고 &lt;code&gt;GPU&lt;/code&gt; 오버랩 향상&lt;/li&gt;
&lt;li&gt;병렬 명령 목록 기록&lt;/li&gt;
&lt;li&gt;그래프의 미사용 리소스 및 패스 컬링&lt;/li&gt;
&lt;li&gt;API 사용 및 리소스 의존성 유효성 검사&lt;/li&gt;
&lt;li&gt;RDG 인사이트에서 그래프 구조체 및 메모리 수명 시각화&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;렌더 그래프 API는 Deffered 렌더러와 모바일 렌더러 및 관련 플러그인에 맞춰 전화되었다. 특히 위에서 설명한 고급 기능이 필요한 경우, 모든 고수준 렌더링 코드는 RDG로 작성해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;
  
  
  셰이더 파라미터 구조체
&lt;/h1&gt;

&lt;p&gt;RDG는 셰이더 파라미터 구조체 시스템을 향한 익스텐션을 통해 그래프 의존성을 표현한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HLSL 소스 파일의 셰이더 입력:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hlsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float2&lt;/span&gt; &lt;span class="n"&gt;ViewportSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float4&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="n"&gt;World&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float3&lt;/span&gt; &lt;span class="n"&gt;FooBarArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kt"&gt;Texture2D&lt;/span&gt; &lt;span class="n"&gt;BlueNoiseTexture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;SamplerState&lt;/span&gt; &lt;span class="n"&gt;BlueNoiseSampler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;Texture2D&lt;/span&gt; &lt;span class="n"&gt;SceneColorTexture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;SamplerState&lt;/span&gt; &lt;span class="n"&gt;SceneColorSampler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;RWTexture2D&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;float4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SceneColorOutput&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 셰이더 파라미터는 플랫 C++ 데이터 구조체로도 표현할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;이상적인 C++ 버전:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;FMyShaderParameters&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FVector2D&lt;/span&gt; &lt;span class="n"&gt;ViewportSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FVector4&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;World&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FVector&lt;/span&gt; &lt;span class="n"&gt;FooBarArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="n"&gt;FRHITexture&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BlueNoiseTexture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FRHISamplerState&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BlueNoiseSampler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FRHITexture&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SceneColorTexture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FRFISamplerState&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SceneColorSampler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FRHIUnorderedAccessView&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SceneColorOutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;셰이더 파라미터 구조체는 이를 위해 일련의 선언 매크로를 사용한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;셰이더 파라미터 구조체:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;BEGIN_SHADER_PARAMETER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FMyShaderParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* MODULE_API_TAG */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FVector2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ViewportSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FVector4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;World&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_ARRAY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FVector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FooBarArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Texture2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlueNoiseTexture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_SAMPLER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SamplerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlueNoiseSampler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Texture2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneColorTexture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_SAMPLER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SamplerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneColorSampler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RWTexture2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneColorOutput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;END_SHADER_PARAMETER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이러한 매크로는 동일한 플랫 C++ 데이터 구조체와 컴파일 시간 반영 메타데이터를 생성한다. 이 데이터는 구조체의 스태틱 멤버로 액세스 가능하다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;컴파일 시간 반영 데타데이터:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;FShaderParametersMetadata&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ParameterMetadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FMyShaderParameters&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FTypeInfo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetStructMetadata&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 메타데이터는 파라미터를 &lt;code&gt;RHI&lt;/code&gt;에 다이내믹하게 바인딩하는 데 필요한 구조체의 런타임 트래버셜을 활성화한다. 각 멤버에 대해 확인할 수 있는 정보에는 &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;C++ type&lt;/code&gt;, &lt;code&gt;HLSL type&lt;/code&gt;, &lt;code&gt;Byte Offset&lt;/code&gt; 등이 있다.&lt;br&gt;
&lt;code&gt;RDG&lt;/code&gt;는 이 &lt;code&gt;메타데이터&lt;/code&gt;를 사용해 &lt;strong&gt;패스 파라미터&lt;/strong&gt;를 탐색한다.&lt;/p&gt;
&lt;h1&gt;
  
  
  Shader Binding
&lt;/h1&gt;

&lt;p&gt;각 셰이더 파라미터 구조체는 &lt;code&gt;FShader&lt;/code&gt;와 짝을 이루어 RHI 명령 목록을 제출하는데 필요한 바인딩을 생성한다.&lt;/p&gt;

&lt;p&gt;바인딩을 생성하려면 &lt;code&gt;FShader&lt;/code&gt; 파생 클래스에 &lt;code&gt;FParameters&lt;/code&gt; 유형으로 파라미터 구조체를 선언한다.&lt;/p&gt;

&lt;p&gt;이 작업은 &lt;code&gt;inline&lt;/code&gt;으로 정의하거나 &lt;code&gt;typedef&lt;/code&gt; 디렉티브를 사용하여 수행할 수 있다. 그 다음, &lt;code&gt;SHADER_USE_PARAMETER_STRUCT&lt;/code&gt; 매크로를 사용해 바인딩을 등록할 클래스의 생성자를 만든다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Shader Class&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FMyShaderCS&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;FGlobalShader&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DECLARE_GLOBAL_SHADER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FMyShaderCS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 이 FShader 인스턴스와 함께 FParameter 바인딩을 등록할 생성자를 만든다.&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_USE_PARAMETER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FMyShaderCS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FGlobalShader&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 인라인 정의나 디렉티브로 셰이더에 FParameters 유형을 할당한다.&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;FParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FMyShaderParameters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RHI 명령 목록에 셰이더 파라미터를 바인딩하려면 구조체를 인스턴스화하고 데이터를 채운 다음 &lt;code&gt;SetShaderParameters&lt;/code&gt; 유틸리티 함수를 호출한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;파라미터 할당하기:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;TShaderMapRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FMyShaderCS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ComputeShader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShaderMap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;RHICmdList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetComputeShader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ComputeShader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetComputeShader&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;FMyShaderCS&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FParameters&lt;/span&gt; &lt;span class="n"&gt;ShaderParameters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 파라미터 할당&lt;/span&gt;
&lt;span class="n"&gt;ShaderParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewportSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ShaderParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;World&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ShaderParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FooBarArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 파라미터 제출&lt;/span&gt;
&lt;span class="n"&gt;SetShaderParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RHICmdList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ComputeShader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ComputeShader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetComputeShader&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;ShaderParameters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;RHICmdList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DispatchComputeShader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GroupCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GroupCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GroupCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Uniform Buffers
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;유니폼 버퍼(Uniform Buffers)&lt;/strong&gt;는 파라미터를 RHI 리소스로 그룹화한다. 이 리소스는 그 자체로 셰이더 파라미터로서 바인딩된다.  각 유니폼 버퍼는 &lt;code&gt;HLSL&lt;/code&gt;에서 글로벌 네임스페이스를 정의한다. &lt;br&gt;
유니폼 버퍼는 &lt;code&gt;BEGIN_UNIFORM_BUFFER_STRUCT&lt;/code&gt; 및 &lt;code&gt;END_UNIFORM_BUFFER_STRUCT&lt;/code&gt; 매크로를 사용해 선언한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;유니폼 버퍼 정의하기:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;BEGIN_UNIFORM_BUFFER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FSceneTextureUniformParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RENDERER_API&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Texture2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneColorTexture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SamplerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneColorTextureSampler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Texture2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneDepthTexture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_TEXTURE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SamplerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneDepthTextureSampler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="n"&gt;END_UNIFORM_BUFFER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C++ 소스 파일에서 &lt;code&gt;IMPLEMENT_UNIFORM_BUFFER_STRUCT&lt;/code&gt;를 사용해 셰이더 시스템으로 유니폼 버퍼 정의를 등록하고 HLSL 정의를 생성한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;유니폼 버퍼 구현하기:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;IMPLEMENT_UNIFORM_BUFFER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FSceneTextureUniformParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SceneTextureStruct"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;유니폼 버퍼 파라미터는 컴파일된 셰이더에 의해 자동으로 생성되며, &lt;code&gt;UniformBuffer.Member&lt;/code&gt; 구문으로 액세스할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HLSL의 유니폼 버퍼:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 유니폼 버퍼 선언을 포함한 파일 생성. Common.ush에 의해 자동으로 포함됨.&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"/Engine/Generated/GeneratedUniformBuffers.ush"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// 유니폼 버퍼 멤버를 구조체처럼 참조한다.&lt;/span&gt;
&lt;span class="n"&gt;Texture2DSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SceneTexturesStruct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SceneColorTexture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneTexturesStruct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SceneColorTextureSampler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이제 &lt;code&gt;SHADER_PARAMETER_STRUCT_REF&lt;/code&gt; 매크로를 사용해 부모 셰이더 파라미터 구조체에서 유니폼 버퍼를 파라미터로 포함시킬 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SHADER_PARAMETER_STRUCT_REF&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;BEGIN_SHADER_PARAMETER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FParameters&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="c1"&gt;// 레퍼런스 카운트된 TUniformBufferRef&amp;lt;FSceneTexturesUniformParameters&amp;gt; 인스턴스를 정의한다.&lt;/span&gt;
    &lt;span class="n"&gt;SHADER_PARAMETER_STRUCT_REF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FSceneTextureUniformParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneTextures&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;END_SHADER_PARAMETER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Static Bindings
&lt;/h1&gt;

&lt;p&gt;셰이더 파라미터는 각 셰이더에 고유하게 바인딩된다. &lt;code&gt;vertex&lt;/code&gt;, &lt;code&gt;pixel&lt;/code&gt; 등의 각 셰이더 단계에는 별도의 셰이더가 필요하다. 셰이더는 RHI 명령 목록에서 &lt;code&gt;Set{Graphics, Compute}PipelineState&lt;/code&gt;를 사용해 &lt;em&gt;Pipeline State Object (PSO)&lt;/em&gt;로 함께 바인딩된다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;명령 목록에서 파이프라인 스테이트를 바인딩하면, &lt;strong&gt;모든 셰이더 바인딩이 무효화된다.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;PSO&lt;/code&gt;를 설정한 다음에 모든 셰이더 파라미터를 바인딩해야 한다. 예를 들어 &lt;code&gt;PSO&lt;/code&gt;를 공유하는 일반적인 DrawCall의 명령 흐름을 살펴보자.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PSO A 설정&lt;/li&gt;
&lt;li&gt;각 DrawCall에 대해 아래 작업 수행

&lt;ul&gt;
&lt;li&gt;vertex shader parameter 설정&lt;/li&gt;
&lt;li&gt;pixel shader parameter 설정&lt;/li&gt;
&lt;li&gt;draw&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;PSO B 설정&lt;/li&gt;

&lt;li&gt;각 DrawCall에 대해 아래 작업 수행

&lt;ul&gt;
&lt;li&gt;vertex shader parameter 설정&lt;/li&gt;
&lt;li&gt;pixel shader parameter 설정&lt;/li&gt;
&lt;li&gt;draw&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;이 접근법의 문제는 렌더러의 mesh draw 명령이 여러 pass와 view 간에 cache가 공유된다는 점이다. &lt;br&gt;
frame마다 각 pass/view 조합별로 각기 다른 draw 명령 세트를 생성해야 한다면, 매우 비효율적일 것이다. 하지만 mesh draw 명령은 pass/view uniform buffer 리소스를 알아야 올바르게 binding을 수행할 수 있다. 이 문제를 해결하기 위해 uniform buffer에는 &lt;strong&gt;static&lt;/strong&gt; binding model이 사용된다.&lt;/p&gt;

&lt;p&gt;static binding으로 선언한 uniform buffer는 개별 셰이더의 &lt;strong&gt;고유 슬롯&lt;/strong&gt;이 아니라 RHI 명령 목록과 직접 연결된 &lt;strong&gt;static slot&lt;/strong&gt;에 바인딩된다. 셰이더가 uniform buffer를 요청하면 명령 목록은 static slot에서 직접 바인딩을 가져온다. 이렇게 하면 바인딩이 &lt;strong&gt;PSO&lt;/strong&gt; 빈도가 아닌 &lt;strong&gt;pass&lt;/strong&gt; 빈도로 이루어진다.&lt;/p&gt;

&lt;p&gt;아래는 위의 예시와 동일하지만 셰이더 입력을 static uniform buffer에서 가져온다는 차이가 있다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static uniform buffer 설정&lt;/li&gt;
&lt;li&gt;PSO A 설정&lt;/li&gt;
&lt;li&gt;각 draw call에 대해 아래 작업 수행

&lt;ul&gt;
&lt;li&gt;draw&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PSO B 설정&lt;/li&gt;
&lt;li&gt;각 draw call에 대해 아래 작업 수행

&lt;ul&gt;
&lt;li&gt;draw&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 모델을 사용하면 각 draw call이 명령 목록에서 셰이더 바인딩을 상속할 수 있다.&lt;/p&gt;
&lt;h2&gt;
  
  
  Static Uniform Buffers 정의하기
&lt;/h2&gt;

&lt;p&gt;static binding으로 uniform buffer를 정의하려면, &lt;br&gt;
&lt;code&gt;IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT&lt;/code&gt; 매크로를 사용한다. 추가 슬롯을 선언해야 한다. 이는 &lt;code&gt;IMPLEMENT_STATIC_UNIFORM_BUFFER_SLOT&lt;/code&gt; 매크로에 지정된다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;여러 static uniform buffer 정의가 동일한 static slot을 참조할 수 있지만, binding할 수 있는 정의는 한 번에 하나뿐이다. 가급적 엔진 내 총 슬롯 수를 줄일 수 있도록 슬롯을 재사용하는 것이 좋다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Static Uniform Buffers:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 이름으로 unique static slot을 정의한다.&lt;/span&gt;
&lt;span class="n"&gt;IMPLEMENT_STATIC_UNIFORM_BUFFER_SLOT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SceneTextures&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// SceneTextures slot에 static 바인딩하여 SceneTexturesStruct uniform buffer를 정의한다.&lt;/span&gt;
&lt;span class="n"&gt;IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FSceneTextureUniformParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SceneTexturesStruct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneTextures&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 동일한 static slot으로 MobileSceneTextures uniform buffer를 정의한다.&lt;/span&gt;
&lt;span class="n"&gt;IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FMobileSceneTextureUniformParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"MobileSceneTexturesStruct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneTextures&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;RHICmdList.SetStaticUniformBuffers&lt;/code&gt; 메서드를 사용해 static uniform buffer를 binding한다. &lt;strong&gt;RDG는 각 pass를 실행하기 전에 자동으로 static uniform buffer를 명령 목록에 binding한다.&lt;/strong&gt; 모든 static uniform buffer는 pass parameter struct에 포함되어야 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Render Graph Builder
&lt;/h1&gt;

&lt;p&gt;렌더 종속성 그래프는 간단히 사용할 수 있도록 설계되었다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FRDGBuilder&lt;/code&gt; 인스턴스를 인스턴스화하고, 리소스를 생성하며, 패스를 추가해 그래프를 구성한다. 그 다음 &lt;code&gt;FRDGBuilder::Execute&lt;/code&gt;를 호출해 그래프를 컴파일하고 실행한다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FRDGBuilder::CreateTexture&lt;/code&gt;로 텍스처를 생성하거나 &lt;code&gt;FRDGBuilder::CreateBuffer&lt;/code&gt;로 버퍼를 만든다.

&lt;ul&gt;
&lt;li&gt;이러한 메서드에서는 디스크립터만 할당된다. 기반 RHI 리소스는 나중에 실행 과정에서 할당된다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;FRDGBuilder::AddPass&lt;/code&gt; 함수를 사용해 패스를 추가하여 Pass 파라미터 구조체와 실행 lambda를 argument로 지정한다.

&lt;ul&gt;
&lt;li&gt;Pass 파라미터 구조체는 RDG 리소스를 포함한 파라미터로 셰이더 파라미터 구조체를 확장한다.&lt;/li&gt;
&lt;li&gt;RDG는 이러한 파라미터를 사용해 그래프의 패스와 일시적 리소스 수명 사이의 종속성을 찾아낸다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GraphBuilder::AllocParameters&lt;/code&gt;로 패스 파라미터를 할당하고 실행 람다에 사용된 모든 관련 RDG 리소스를 지정한다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;패스 실행 람다는 그래프 실행 중 작업을 기록해 RHI 명령 목록에 제출한다.

&lt;ul&gt;
&lt;li&gt;Compute Pass(비동기 및 그래픽 컴퓨트 사이의 공유 인터페이스)에 &lt;code&gt;FRHIComputeCommandList&lt;/code&gt;를 사용하거나 레스터 패스에 &lt;code&gt;FRHICommandList&lt;/code&gt;를 사용한다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FRHICommandListImmediate&lt;/code&gt;를 사용하면 패스를 병렬 실행할 수 없으므로 이 방법은 반드시 필요한 경우가 아니면 사용하지 않는 것이 좋다.&lt;/li&gt;
&lt;li&gt;모든 패스 람다가 Thread Safe인 것이 이성적이지만, 실제로는 실행 중 일부 패스의 RHI 리소스를 RenderThread에서 생성하거나 잠가야 한다. 이 경우 즉각 명령 목록(FRHICommandListImmediate)을 사용해야한다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;아래의 예시를 참고하자.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Graph Builder:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FRDGBuilder&lt;/span&gt; &lt;span class="n"&gt;GraphBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RHICmdList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;FMyShaderCS&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FParameters&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;PassParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GraphBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllocParameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FMyShaderCS&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FParameters&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;PassParameters&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;SceneColorTexture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SceneColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;PassParameters&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;SceneColorSampler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TStaticSamplerState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SF_Point&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AM_Clamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AM_Clamp&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;GetRHI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;PassParameters&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;SceneColorOutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GraphBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateUAV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewSceneColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;GraphBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddPass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// printf 시멘틱을 사용해 프로파일러의 패스에 친근한 이름을 지정합니다.&lt;/span&gt;
        &lt;span class="n"&gt;RDG_EVENT_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyShader %d%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="c1"&gt;// RDG에 파라미터 구조체를 전달합니다.&lt;/span&gt;
        &lt;span class="n"&gt;PassParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// 컴퓨트 명령이 발생한다.&lt;/span&gt;
        &lt;span class="n"&gt;ERDGPassFlags&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Compute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// 실행 시까지 연기된다. 다른 패스와 병렬 실행될 수 있다.&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PassParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ComputeShader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GroupCount&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;FRHIComputeCommandList&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;RHICmdList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;FComputeShaderUtils&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RHICmdList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ComputeShader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PassParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GroupCount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 그래프를 실행한다.&lt;/span&gt;
    &lt;span class="n"&gt;GraphBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그래프 빌더 API는 단일 스레드 방식이며, 한 번에 하나의 인스턴스만 인스턴스화 가능하다. 계층 그래프나 side-by-side 그래프는 제외된다. Deffered Renderer와 Mobile Renderer는 모두 각 씬 렌더 발동에 단일 빌더 인스턴스를 사용한다.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup and Execute Timelines
&lt;/h1&gt;

&lt;p&gt;RDG는 렌더 파이프라인을 두 가지 타임라인으로 나눈다. &lt;strong&gt;구성&lt;/strong&gt; 및 &lt;strong&gt;실행&lt;/strong&gt; 이다.&lt;/p&gt;

&lt;p&gt;그래프는 구성 타임라인에서 빌드된다. 여기서 리소스 생성과 렌더 파이프라인 환경설정 분기가 이루어진다. 모든 RHI 명령은 Pass Lambda로 연기되고, Lambda는 실행 타임라인에서 호출된다.&lt;/p&gt;

&lt;p&gt;Pass 실행이 병렬화될 수 있으므로 Pass Lambda에서 지정된 코드는  부작용이 없어야 하며, 명령을 명령 목록에 기록하기만 해야 한다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro9y4neywa2kdffggw33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro9y4neywa2kdffggw33.png" alt=" " width="660" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RDG가 없는 경우에는 렌더링 기능이 하나의 타임라인에 작성된다. 이 타임라인에서 구성과 실행이 모두 이루어진다. RHI 명령은 파이프라인 분기 및 리소스 할당에 따라 직접 기록되고 제출된다.&lt;/p&gt;

&lt;p&gt;RDG가 있으면 사용자 제공 패스 실행 람다를 통해 구성 코드가 실행과 분리된다. &lt;br&gt;
RDG는 패스 실행 람다를 호출하기 전에 추가 컴파일 단계를 수행한다. 실행은 여러 스레드에 걸쳐 수행되며, 람다를 호출해 렌더 명령을 RHI 명령 목록에 기록한다.&lt;/p&gt;

&lt;h1&gt;
  
  
  RDG Utilities Functions
&lt;/h1&gt;

&lt;h1&gt;
  
  
  RDG Resources and Views
&lt;/h1&gt;

</description>
      <category>programming</category>
      <category>unrealengine</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>[UE] GameMode, GameState, Player State, Player Controller, Pawn</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Tue, 14 Oct 2025 07:09:41 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/ue-gamemode-gamestate-player-state-player-controller-pawn-54d9</link>
      <guid>https://dev.to/seongcheoljeon/ue-gamemode-gamestate-player-state-player-controller-pawn-54d9</guid>
      <description>&lt;h1&gt;
  
  
  GameMode, GameState, PlayerState, PlayerController, Pawn
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Game Mode&lt;/th&gt;
&lt;th&gt;Game State&lt;/th&gt;
&lt;th&gt;Player State&lt;/th&gt;
&lt;th&gt;Player Controller&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Server Only&lt;/td&gt;
&lt;td&gt;Server &amp;amp; All Clients&lt;/td&gt;
&lt;td&gt;Server &amp;amp; All Clients&lt;/td&gt;
&lt;td&gt;Server &amp;amp; Owning Client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Default Classes&lt;/strong&gt;&lt;br&gt;Pawn&lt;br&gt;Player Controller&lt;br&gt;HUD&lt;br&gt;Rules&lt;br&gt;Player Eliminated&lt;br&gt;Respawning Players&lt;br&gt;Match State&lt;br&gt;Warmup Time&lt;br&gt;Match Time&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;State of the Game&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Top Scoring Players&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Teams in the Lead&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Team Scores&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Array of Player States&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;State of the Player&lt;/strong&gt;&lt;br&gt;SCore&lt;br&gt;Defeats&lt;br&gt;Carried Ammo&lt;br&gt;Team&lt;br&gt;Slower Net Update(Player State에서는 Net Update 속도가 느리다)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Access to the HUD&lt;/strong&gt;&lt;br&gt;Display Messages&lt;br&gt;Update HUD Health&lt;br&gt;Update HUD Score&lt;br&gt;Update HUD Defeats&lt;br&gt;Update HUD Ammo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pawn&lt;/th&gt;
&lt;th&gt;HUD/Widget&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Server &amp;amp; All Clients&lt;/td&gt;
&lt;td&gt;Owning Client Only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Game Mode&lt;/code&gt;는 &lt;code&gt;Server&lt;/code&gt;만 가지고 있다. &lt;code&gt;Client&lt;/code&gt;가 &lt;code&gt;Game Mode&lt;/code&gt;에 접근하면 &lt;code&gt;nullptr&lt;/code&gt;을 반환한다.&lt;/p&gt;

&lt;p&gt;반면, &lt;code&gt;Game State&lt;/code&gt;는 &lt;code&gt;Server&lt;/code&gt;와 &lt;code&gt;Client&lt;/code&gt; 모두 가지고 있다. &lt;code&gt;Server&lt;/code&gt;의 정보가 &lt;code&gt;Replicated&lt;/code&gt;되어 &lt;code&gt;Game State&lt;/code&gt;에 내려오고 이를 통해 &lt;code&gt;Client&lt;/code&gt;에 정보가 전달된다.&lt;/p&gt;




&lt;h2&gt;
  
  
  GameMode, GameState, GameInstance 비교
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GameMode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;게임 규칙 정의&lt;br&gt;&lt;code&gt;Server&lt;/code&gt; 측에서만 존재하며, &lt;code&gt;Client&lt;/code&gt; 측에서는 &lt;code&gt;복제(Replicated)&lt;/code&gt;되지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GameState&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;GameMode&lt;/code&gt;가 정의한 규칙에 따라 게임의 현재 상태를 추적.&lt;br&gt;&lt;code&gt;GameState&lt;/code&gt;는 모든 &lt;code&gt;Client&lt;/code&gt;에 &lt;code&gt;복제(Replicated)&lt;/code&gt;된다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GameInstance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;게임 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>programming</category>
      <category>gamedev</category>
      <category>unrealengine</category>
      <category>cpp</category>
    </item>
    <item>
      <title>[UE] Subsystem</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Tue, 14 Oct 2025 05:14:18 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/ue-subsystem-31dd</link>
      <guid>https://dev.to/seongcheoljeon/ue-subsystem-31dd</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Subsystem

&lt;ul&gt;
&lt;li&gt;Subsystem 종류&lt;/li&gt;
&lt;li&gt;Subsystem을 사용하는 이유&lt;/li&gt;
&lt;li&gt;UEditorSubsystem&lt;/li&gt;
&lt;li&gt;UGameInstanceSubsystem을 상속받는 클래스의 생명주기 (Life Time)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Game Instance vs Game Instance Subsystem&lt;/li&gt;

&lt;/ul&gt;




&lt;h1&gt;
  
  
  Subsystem
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Subsystem 종류
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UEngineSubsystem&lt;/li&gt;
&lt;li&gt;UEditorSubsystem&lt;/li&gt;
&lt;li&gt;UGameInstanceSubsystem&lt;/li&gt;
&lt;li&gt;ULocalPlayerSubsystem&lt;/li&gt;
&lt;li&gt;UWorldSubsystem&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Subsystem 타입&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Life Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Engine&lt;/td&gt;
&lt;td&gt;UEngineSubsystem&lt;/td&gt;
&lt;td&gt;Editor, In-Game&lt;br&gt;&lt;br&gt;&lt;strong&gt;시작&lt;/strong&gt;&lt;br&gt;Engine Subsystem의 Module 로드 -&amp;gt; Module의 Startup() 함수 반환 -&amp;gt; Initialize() 호출&lt;br&gt;&lt;br&gt;&lt;strong&gt;끝&lt;/strong&gt;&lt;br&gt;Module의 Shutdown() 함수 변환 -&amp;gt; DeInitialize() 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Editor&lt;/td&gt;
&lt;td&gt;UEditorSubsystem&lt;/td&gt;
&lt;td&gt;Editor 시작 시&lt;br&gt;&lt;br&gt;&lt;strong&gt;시작&lt;/strong&gt;&lt;br&gt;Editor Subsystem의 Module이 로드 -&amp;gt; Module의 Startup() 함수 변환 -&amp;gt; Initialize() 호출&lt;br&gt;&lt;br&gt;&lt;strong&gt;끝&lt;/strong&gt;&lt;br&gt;Module의 Shutdown() 함수 변환 -&amp;gt; DeInitialize()를 호출:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Game Instance&lt;/td&gt;
&lt;td&gt;UGameInstanceSubsystem&lt;/td&gt;
&lt;td&gt;In-Game 시작 ~ In-Game 종료&lt;br&gt;&lt;br&gt;&lt;strong&gt;시작&lt;/strong&gt;&lt;br&gt;GameInstance Subsystem의 Module이 로드 -&amp;gt; Module의 Startup() 함수 반환 -&amp;gt; Initialize() 호출&lt;br&gt;&lt;br&gt;&lt;strong&gt;끝&lt;/strong&gt;&lt;br&gt;Module의 Shutdown() 함수 반환 -&amp;gt; DeInitialize() 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local Player&lt;/td&gt;
&lt;td&gt;ULocalPlayerSubsystem&lt;/td&gt;
&lt;td&gt;ULocalPlayer의 LifeTime&lt;br&gt;(Level이 여러개면, 해당 Level에 존재하는 ULocalPlayer의 LifeTime)&lt;br&gt;&lt;br&gt;&lt;strong&gt;시작&lt;/strong&gt;&lt;br&gt;LocalPlayer Subsystem의 Module 로드 -&amp;gt; Module의 Startup() 함수 변환 -&amp;gt; Initialize() 호출&lt;br&gt;&lt;br&gt;&lt;strong&gt;끝&lt;/strong&gt;&lt;br&gt;Module의 Shutdown() 함수 변환 -&amp;gt; DeInitialize() 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;World&lt;/td&gt;
&lt;td&gt;UWorldSubsystem&lt;/td&gt;
&lt;td&gt;UWorld의 LifeTime&lt;br&gt;(Level이 여러개이면, Level 별로 존재함)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Engine Subsystem&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UMyEngineSubsystem&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;UEngineSubsystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;UMyEngineSubsystem&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;MySubsystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GEngine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetEngineSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UMyEngineSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;span class="c1"&gt;// Editor Subsystem&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UMyEditorSubsystem&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;UEditorSubsystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;UMyEidotrSubsystem&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;MySubsystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GEditor&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetEditorSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UMyEditorSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;span class="c1"&gt;// GameInstance Subsystem&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UMyGameSubsystem&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;UGameInstanceSubsystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;UGameInstance&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;GameInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetGameInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;UMyGameSubsystem&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;MySubsystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameInstance&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UMyGameSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;span class="c1"&gt;// LocalPlayer Subsystem&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UMyPlayerSubsystem&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ULocalPlayerSubsystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;UGameInstance&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;GameInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetGameInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ULocalPlayer&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;LocalPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameInstance&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetFirstGamePlayer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;UMyPlayerSubsystem&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;MySubsystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LocalPlayer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UMyPlayerSubsystem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Reference&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.epicgames.com/documentation/ko-kr/unreal-engine/programming-subsystems-in-unreal-engine?application_version=5.6" rel="noopener noreferrer"&gt;UnrealEngine 프로그래밍 서브시스템&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.epicgames.com/community/learning/tutorials/XvMJ/unreal-engine-programming-subsystems-extra-community-info" rel="noopener noreferrer"&gt;UnrealEngine 프로그래밍 서브시스템 (extra community info)&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Subsystem을 사용하는 이유
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Subsystem&lt;/code&gt; 내에 이미 존재하는 기능을 가져와서 사용하므로 다음과 같은 이점이 있다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engine Class Override를 피할 수 있다.&lt;/li&gt;
&lt;li&gt;API 추가를 피할 수 있다.&lt;/li&gt;
&lt;li&gt;Subsystem 기능이 Blueprint에 자동 노출되고 Blueprint로 Subsystem을 액세스할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  UEditorSubsystem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UEditorActorSubsystem

&lt;ul&gt;
&lt;li&gt;TArray GetSelectedlevelActors()&lt;/li&gt;
&lt;li&gt;TArray GetAllLevelActors()&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  UGameInstanceSubsystem을 상속받는 클래스의 생명주기(Life Time)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GameInstance Subsystem&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UMyGameSubsystem&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;UGameInstanceSubsystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;위와 같이 &lt;code&gt;UGameInstanceSubsystem&lt;/code&gt;을 상속받는 클래스가 존재한다면,&lt;/p&gt;

&lt;p&gt;UGameInstance 생성 -&amp;gt; UMyGameSubsystem 인스턴스 생성&lt;br&gt;
UGameInstance 초기화 -&amp;gt; UMyGameSubsystem 인스턴스에서 Initialize()가 호출&lt;/p&gt;

&lt;p&gt;UGameInstance 종료 -&amp;gt; UMyGameSubsystem 인스턴스에서 DeInitialize()가 호출&lt;br&gt;
DeInitialize()가 호출된 시점에서 UMyGameSubsystem 인스턴스에 대한 참조가 삭제된다. 더 이상 참조가 없으면 UMyGameSubsystem 인스턴스는 &lt;code&gt;Garbage Collection&lt;/code&gt; 대상이 된다.&lt;/p&gt;




&lt;p&gt;Game Instance vs Game Instance Subsystem&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Game Instance&lt;/th&gt;
&lt;th&gt;Game Instance Subsystem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Game 생성 시, Spawn 된다.&lt;/td&gt;
&lt;td&gt;Game Instance가 생성 된 후에 생성된다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Game이 종료될 때까지 소멸되지 않는다(Game 종료 시, 소멸).&lt;/td&gt;
&lt;td&gt;Game Instance 종료 시, 소멸되고 Garbage Collector에서 처리된다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;게임에서 레벨을 이동하는 경우(던전 입장, 마을 이동 등)가 빈번하게 발생한다. 또한 FPS 게임의 경우, 한 게임이 끝나고 다시 게임이 시작되는 경우가 비번히 발생한다.&lt;/p&gt;

&lt;p&gt;그렇기 때문에 Game이 종료 될 때까지 소멸하지 않는 Game Instance보다 &lt;code&gt;**Game Instance Subsystem을 사용하는 것이 더 유리하다.**&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Game Instance Subsystem을 사용하면, Engine Class Override를 피할 수 있고 코드의 재사용성을 높일 수 있다.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>unrealengine</category>
    </item>
    <item>
      <title>[UE] Unreal Performance Optimization Learning Path</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Wed, 01 Oct 2025 02:19:02 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/unreal-performance-optimization-learning-path-1k90</link>
      <guid>https://dev.to/seongcheoljeon/unreal-performance-optimization-learning-path-1k90</guid>
      <description>&lt;h1&gt;
  
  
  UnrealEngine 최적화 관련 사이트 정리
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://dev.epicgames.com/community/learning/paths/Rkk/unreal-engine-unreal-performance-optimization-learning-path" rel="noopener noreferrer"&gt;https://dev.epicgames.com/community/learning/paths/Rkk/unreal-engine-unreal-performance-optimization-learning-path&lt;/a&gt;&lt;/p&gt;

</description>
      <category>unrealengine</category>
      <category>optimization</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>[UE] ClassRedirects</title>
      <dc:creator>Seongcheol Jeon</dc:creator>
      <pubDate>Mon, 15 Sep 2025 04:47:32 +0000</pubDate>
      <link>https://dev.to/seongcheoljeon/ue-classredirects-3l70</link>
      <guid>https://dev.to/seongcheoljeon/ue-classredirects-3l70</guid>
      <description>&lt;h1&gt;
  
  
  클래스명 혹은 모듈 이름을 변경할 때, 참조하고 있는 블루프린트가 존재할 때
&lt;/h1&gt;

&lt;p&gt;클래스명 또는 모듈 이름을 변경하려고 할 때, 참조하고 있는 블루프린트가 존재하면 그 블루프린트의 Parent Class는 깨진다.&lt;/p&gt;

&lt;p&gt;이럴 때는 &lt;code&gt;Config/DefaultEngine.ini&lt;/code&gt; 파일에서 다음과 같이 설정하면 된다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CoreRedirects&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;ClassRedirects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OldName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ClassA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;NewName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ClassB"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이것을 "DefaultEngine.ini" 파일에 추가한 후, 에디터를 실행하여 ClassA를 참조하는 모든 블루프린트를 다시 컴파일/저장 후 종료한다. &lt;br&gt;
"DefaultEngine.ini"파일에서 추가한 내용을 제거하고 다시 엔진을 실행하여 제대로 되었는지 확인한다.&lt;/p&gt;

&lt;p&gt;continue...&lt;/p&gt;

</description>
      <category>programming</category>
      <category>unrealengine</category>
    </item>
  </channel>
</rss>
