{"id":499690,"date":"2026-10-22T04:01:16","date_gmt":"2026-10-22T01:01:16","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=499690"},"modified":"2026-10-22T04:01:16","modified_gmt":"2026-10-22T01:01:16","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=499690","title":{"rendered":"Render Graph \u043d\u0430 Rust \u0438 Vulkan"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0442\u0435\u043c, \u043a\u0442\u043e \u0443\u0436\u0435 \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0441\u0432\u043e\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u044b \u043d\u0430 Vulkan. \u042f \u043b\u0438\u0448\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 Vulkan-\u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439, \u043a\u0442\u043e \u0438\u043c\u0435\u0435\u0442 \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Vulkan, \u0437\u0430\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c. \u041a\u0430\u043a\u0438\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c? \u041a\u0430\u043a\u0438\u0435 \u0444\u0438\u0447\u0438 GPU \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438, \u0430 \u043a\u0430\u043a\u0438\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438? \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435? \u0410 \u0435\u0449\u0435 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0438 async compute&#8230;<\/p>\n<p>\u0421\u0430\u043c\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 &#8212; \u0442\u043e, \u0447\u0442\u043e GPU \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0437\u043d\u044b\u0435 (IMR vs TBDR, UMA vs Discrete). \u041a\u043e\u0433\u0434\u0430 \u043f\u044b\u0442\u0430\u0435\u0448\u044c\u0441\u044f \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u043e\u0434\u043d\u0438\u043c API \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0435\u0433\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0448\u044c \u043a \u0432\u0435\u0442\u043a\u0430\u043c, \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0432\u0435\u0442\u043a\u0430\u043c \u043a\u043e\u0434\u0430.<\/p>\n<p>Vulkan 1.3 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0438, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u041f\u041a, \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043c \u043a\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u0431\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0441 \u043d\u0435\u0433\u043e. \u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 GPU \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0441\u0435 \u043c\u0435\u043d\u044c\u0448\u0435, \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u041f\u041a-\u0440\u0435\u043d\u0434\u0435\u0440 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u043c\u0438 (\u0430 \u0442\u043e \u0438 \u0431\u0435\u0437 \u043d\u0438\u0445) \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0436\u0435 \u0434\u043e\u0439\u0442\u0438 \u0434\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430, \u044f \u0432\u0437\u044f\u043b \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u043f\u0440\u043e\u0444\u0438\u043b\u044c <code>VP_LUNARG_desktop_baseline_2024<\/code> \u0438 \u0431\u0440\u0430\u043b \u043e\u0442\u0442\u0443\u0434\u0430 \u0432\u0441\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043b\u0438\u043c\u0438\u0442\u043e\u0432, \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0438 \u0444\u0438\u0447. \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e GPU \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439, \u0445\u043e\u0442\u044f \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u043b\u0438\u043c\u0438\u0442\u044b, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b\u0448\u0435.<\/p>\n<p>\u0418\u0437-\u0437\u0430 \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u0438 Vulkan \u0438 \u043e\u0431\u044a\u0435\u043c\u0430 \u0442\u0435\u043c\u044b \u0434\u0430\u043b\u044c\u0448\u0435 \u044f \u043e\u043f\u0438\u0448\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u044b\u0435 \u0432\u0430\u0436\u043d\u044b\u0435 \u043f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e \u0432\u0435\u0449\u0438, \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u0430 \u0438\u0434\u0435\u044f:<\/p>\n<pre><code class=\"rust\">pub struct RenderContext {    pub(crate) size_dependent: RwLock&lt;SizeDependentResources&gt;,    pub(crate) device: Device,    pub(crate) surface: Surface,    pub(crate) instance: Instance,}impl RenderContext {    pub fn new(window: &amp;Window) -&gt; Arc&lt;Self&gt; {        let instance = Instance::new();        let surface = Surface::new(&amp;instance, window);        let device = Device::new(&amp;instance, &amp;surface);        let size_dependent = RwLock::new(            SizeDependentResources::new(&amp;instance, &amp;surface, &amp;device)        );        Arc::new(Self {            size_dependent,            device,            surface,            instance,        })    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <code>RenderContext<\/code> (\u043e\u043d\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a <code>Arc&lt;RenderContext&gt;<\/code>) \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0438 \u0445\u0440\u0430\u043d\u0438\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 Vulkan-\u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: device, queue \u0438 GPU-\u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b. \u042f \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043b\u043e\u0436\u0438\u043b \u0432 \u043d\u0435\u0435 <code>Send<\/code> \u0438 <code>Sync<\/code>, \u0445\u043e\u0442\u044f \u0431\u044b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b glTF-\u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043d\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439. \u0427\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044f \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435 \u0437\u043d\u0430\u044e, \u0441\u0442\u043e\u0438\u043b\u043e \u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0438\u043b\u0438 \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u0440\u043e\u0449\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0443\u0436\u0435 \u0438\u043c\u0435\u044f \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u00ab\u0433\u043e\u043b\u044b\u0435\u00bb vk-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 <code>Handle<\/code>. <code>Handle<\/code> &#8212; \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430-\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0434\u0430\u0432\u043d\u043e \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 crate &#8212; <code>slotmap<\/code>. Handle-based \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u0434\u043e\u043a\u043b\u0430\u0434\u0435 Frostbite \u043d\u0430 GDC, <a href=\"https:\/\/www.gdcvault.com\/play\/1024612\/FrameGraph-Extensible-Rendering-Architecture-in\" rel=\"noopener nofollow\">\u00abFrameGraph: Extensible Rendering Architecture in Frostbite\u00bb<\/a>: \u0442\u0430\u043c \u043b\u044e\u0431\u043e\u0439 \u0440\u0435\u0441\u0443\u0440\u0441 &#8212; \u043b\u0438\u0448\u044c \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 (<code>idResource<\/code>), \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 FrameGraph. \u042f \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u0442\u0430\u043a \u0436\u0435 \u0438 \u0434\u043b\u044f \u0434\u043e\u043b\u0433\u043e\u0436\u0438\u0432\u0443\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0438 \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"rust\">#[derive(Clone)]pub struct RenderResources {    pub persistent: Arc&lt;ResourcePool&gt;,    pub transient: Arc&lt;TransientResourceCache&gt;,    pub bindless: Arc&lt;Bindless&gt;,}impl RenderResources {    pub fn new(ctx: &amp;Arc&lt;RenderContext&gt;) -&gt; Self {        Self {            bindless: Bindless::new(ctx),            persistent: ResourcePool::new(ctx),            transient: TransientResourceCache::new(),        }    }}pub struct RenderGraphExecutor {    pub ctx: Arc&lt;RenderContext&gt;,    resources: RenderResources,}impl RenderGraphExecutor {    pub fn new(window: &amp;winit::window::Window) -&gt; Arc&lt;Self&gt; {        let ctx = RenderContext::new(window);        Arc::new(Self {            resources: RenderResources::new(&amp;ctx),            ctx,        })    }    pub fn create_render_graph(&amp;self) -&gt; RenderGraph&lt;'_&gt; {        RenderGraph {            transient_cache: self.resources.transient.clone(),            passes: vec![],            _marker: PhantomData,        }    }    pub fn resize(&amp;self, width: u32, height: u32) {        self.ctx.resize(width, height);        self.resources.transient.invalid_cache();    }    pub fn create_texture(&amp;self, desc: &amp;TextureDesc, data: Option&lt;&amp;[u8]&gt;) -&gt; Handle&lt;Texture&gt; {        self.resources            .persistent            .create_texture(&amp;self.ctx, desc, data)    }    pub fn register_bindless_texture(&amp;self, handle: Handle&lt;Texture&gt;) -&gt; u32 {        let texture = self.resources.persistent.get_texture(handle);        self.resources            .bindless            .bind_image_view(&amp;self.ctx, texture.view)            .unwrap()    }   pub fn swapchain_texture(&amp;self) -&gt; Handle&lt;Texture&gt; {        self.resources.persistent.swapchain_texture()    }    pub fn execute(self: &amp;Arc&lt;Self&gt;, rg: &amp;mut RenderGraph&lt;'_&gt;) {        ...    }    \/\/ \u0418 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b}pub struct Texture {    pub image: vk::Image,    pub allocation: Option&lt;Allocation&gt;,    pub view: vk::ImageView,    pub extent: vk::Extent2D,    pub aspect_mask: vk::ImageAspectFlags,}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0418 \u0434\u0430, \u044f \u043d\u0435 \u043a\u043b\u043e\u043d\u0443\u044e <code>vk::Device<\/code> \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0443 \u043c\u0435\u043d\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 <code>SlotMap&lt;Id, vk::*&gt;<\/code>. \u0414\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430 \u0431\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u043e\u043c \u043a\u0430\u0434\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0431\u044b, \u0447\u0442\u043e \u0440\u0435\u0441\u0443\u0440\u0441 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043d\u043e \u044f \u0435\u0435 \u0442\u0430\u043a \u0438 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0438 \u043f\u043e\u0447\u0442\u0438 \u043d\u0435 \u0443\u0434\u0435\u043b\u044f\u043b \u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f.<\/p>\n<p><code>RenderResources<\/code> \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c <code>Clone<\/code>, <code>Send<\/code> \u0438 <code>Sync<\/code>: \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f <code>PassContext<\/code>, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u0430\u0434\u0440 <code>RenderGraphExecutor<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <code>RenderGraph<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\u0445 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u0442 \u043a\u0435\u0448 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 (transient) \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0440\u0435\u0447\u044c \u0441\u0435\u0431\u044f \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 <code>Handle<\/code> \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0441\u0435\u043a\u0443\u0442\u0441\u044f.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>execute<\/code> \u043e\u0434\u043d\u0438\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u044b\u0432\u043e\u0434 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d. \u041e\u043d\u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0432\u043c\u0435\u0449\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c <code>compile<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0431\u0430\u0440\u044c\u0435\u0440\u044b \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p><code>Swapchain Texture<\/code> &#8212; \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0439 <code>Handle<\/code>, \u043d\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u044b\u0439. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a <code>Handle<\/code> \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0443\u044e \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443 <code>resolve()<\/code>, \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f: \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e \u0438\u043d\u0434\u0435\u043a\u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 <code>acquire_next_image()<\/code>, \u0431\u0435\u0440\u0443 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 <code>image<\/code> \u0438 <code>view<\/code> \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u0435\u0436\u043d\u0438\u0445. \u041a\u043e\u0434 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0443\u0436\u0430\u0441\u043d\u043e, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"rust\">{    let backbuffer = self.resources.persistent.swapchain_texture();    let mut resources = self.resources.persistent.inner.write();    let new_image = frame.swapchain_images[image_index as usize];    let texture = resources.textures.get_mut(backbuffer.id).unwrap();    texture.image = new_image;    texture.view = frame.swapchain_image_views[image_index as usize];    resources        .image_access        .entry(new_image)        .or_insert(AccessType::Nothing);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>RenderGraph<\/code> &#8212; \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043a\u0430\u0434\u0440\u0435: \u043f\u0440\u043e\u0445\u043e\u0434\u044b \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0420\u0435\u0441\u0443\u0440\u0441\u044b \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430 \u0442\u0440\u0438 \u0432\u0438\u0434\u0430: \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0435 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435. \u0427\u0442\u043e\u0431\u044b \u0438\u0445 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0442\u0438\u043f\u043e\u0432, \u044f \u0432\u0432\u0435\u043b <code>RgHandle&lt;T&gt;<\/code> \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 <code>ExportHandle&lt;T&gt;<\/code> \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0445; \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0435 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443\u044e\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c <code>Handle<\/code>.  <\/p>\n<pre><code class=\"rust\">pub struct RenderGraph&lt;'a&gt; {    pub passes: Vec&lt;Pass&lt;'a&gt;&gt;,    pub transient_cache: Arc&lt;TransientResourceCache&gt;,    pub _marker: PhantomData&lt;*mut ()&gt;,}impl&lt;'a&gt; RenderGraph&lt;'a&gt; {    pub fn new(cache: Arc&lt;TransientResourceCache&gt;) -&gt; Self {        Self {            transient_cache: cache,            passes: vec![],            _marker: PhantomData,        }    }    pub fn add_pass&lt;S: Into&lt;String&gt;&gt;(&amp;mut self, name: S) -&gt; PassBuilder&lt;'_, 'a&gt; {        PassBuilder::new(self, name.into())    }    pub fn import_texture(&amp;mut self, handle: Handle&lt;Texture&gt;) -&gt; RgHandle&lt;Texture&gt; {        self.transient_cache.import_texture(handle)    }    pub fn export_texture(        &amp;mut self,        handle: RgHandle&lt;Texture&gt;,        final_access: vk_sync::AccessType,    ) -&gt; ExportHandle&lt;Texture&gt; {        self.transient_cache.export_texture(handle, final_access)    }    pub fn import_buffer(&amp;mut self, handle: Handle&lt;Buffer&gt;) -&gt; RgHandle&lt;Buffer&gt; {        self.transient_cache.import_buffer(handle)    }    \/\/ \u0414\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b...}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0445\u043e\u0434 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0443, \u044f \u0432\u0437\u044f\u043b <code>AccessType<\/code> \u0438\u0437 <code>vk-sync<\/code> \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<p>\u041a\u0435\u0448 \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 \u0441\u0430\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043a\u0430\u0434\u0440\u0430\u0445. \u041f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u043e\u043d\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c\u0438.<\/p>\n<p>\u0412 \u043f\u0430\u0441\u0441\u0430\u0445 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0445 \u0438 \u043f\u0438\u0448\u0443\u0448\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445. \u0422\u0438\u043f \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u0438\u043c\u044f \u043f\u0430\u0441\u0441\u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043f\u043e\u043a\u0430 \u0447\u0442\u043e. \u0412\u043e\u0442 \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442:<\/p>\n<pre><code class=\"rust\">#[derive(PartialEq)]pub enum QueueType {    Compute,    Transfer,    Graphics,}pub enum DependencyResource {    ColorAttachment {        handle: RgHandle&lt;Texture&gt;,        load: vk::AttachmentLoadOp,        store: vk::AttachmentStoreOp,        clear_value: vk::ClearColorValue,    },    DepthAttachment {        handle: RgHandle&lt;Texture&gt;,        load: vk::AttachmentLoadOp,        store: vk::AttachmentStoreOp,        clear_value: vk::ClearDepthStencilValue,    },    Buffer(RgHandle&lt;Buffer&gt;),    Texture(RgHandle&lt;Texture&gt;),}pub struct Pass&lt;'a&gt; {    pub name: String,    pub queue_type: QueueType,    pub reads: Vec&lt;(DependencyResource, AccessType)&gt;,    pub writes: Vec&lt;(DependencyResource, AccessType)&gt;,    pub callback: Box&lt;dyn Fn(&amp;mut PassContext) + 'a&gt;,}pub struct PassBuilder&lt;'b, 'a&gt; {    name: String,    queue_type: QueueType,    reads: Vec&lt;(DependencyResource, AccessType)&gt;,    writes: Vec&lt;(DependencyResource, AccessType)&gt;,    rg: &amp;'b mut RenderGraph&lt;'a&gt;,}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412 <code>execute<\/code> \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043b\u0438\u0448\u044c:<\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <code>RenderGraph<\/code><\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0431\u0430\u0440\u044c\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0440\u043e\u0445\u043e\u0434\u0443 \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432\u0441\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d<\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0430\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0431\u0430\u0440\u044c\u0435\u0440\u043e\u0432 \u0443 \u043c\u0435\u043d\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0442\u0443\u043f\u0430\u044f: \u044f \u043d\u0435 \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u044e \u043f\u0440\u043e\u0445\u043e\u0434\u044b \u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u044f\u044e \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435. \u042f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0443\u0441\u044c \u043f\u043e \u0432\u0441\u0435\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c, \u0438 \u0435\u0441\u043b\u0438 <code>AccessType<\/code> \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0443, \u0441\u0442\u0430\u0432\u043b\u044e \u0431\u0430\u0440\u044c\u0435\u0440 \u043f\u0435\u0440\u0435\u0434 \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>vk-sync<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u0438\u0448\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0431\u0430\u0440\u044c\u0435\u0440\u044b 1.0. \u0425\u043e\u0442\u044f \u044f \u0434\u0430\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043d\u043e\u0432\u044b\u0435 \u0431\u0430\u0440\u044c\u0435\u0440\u044b \u0438\u0437 <code>VK_KHR_synchronization2<\/code> (\u0432 Vulkan 1.3 \u043e\u043d\u0438 \u0432\u0445\u043e\u0434\u044f\u0442 \u0432 \u044f\u0434\u0440\u043e), \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u043e\u0433\u0443 \u0441\u043e\u0432\u043c\u0435\u0449\u0430\u0442\u044c \u0438\u0445 \u0441 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438. \u0423 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0431\u0430\u0440\u044c\u0435\u0440\u043e\u0432 \u0444\u043b\u0430\u0433\u0438 \u0438 \u043c\u0430\u0441\u043a\u0438 32-\u0431\u0438\u0442\u043d\u044b\u0435 (<code>u32<\/code>), \u0430 \u0443 \u043d\u043e\u0432\u044b\u0445 64-\u0431\u0438\u0442\u043d\u044b\u0435, \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a <code>u64<\/code> \u0440\u0435\u0448\u0430\u0435\u0442 \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443:<\/p>\n<pre><code class=\"rust\">fn image_barrier2(    image: vk::Image,    range: vk::ImageSubresourceRange,    prev: AccessType,    next: AccessType,    discard: bool,) -&gt; vk::ImageMemoryBarrier2&lt;'static&gt; {    let prev = &amp;[prev];    let next = &amp;[next];    let (src_stage, dst_stage, b) = vk_sync::get_image_memory_barrier(&amp;vk_sync::ImageBarrier {        previous_accesses: prev,        next_accesses: next,        previous_layout: vk_sync::ImageLayout::Optimal,        next_layout: vk_sync::ImageLayout::Optimal,        discard_contents: discard,        src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,        dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,        image,        range,    });    vk::ImageMemoryBarrier2::default()        .src_stage_mask(vk::PipelineStageFlags2::from_raw(src_stage.as_raw() as u64))        .dst_stage_mask(vk::PipelineStageFlags2::from_raw(dst_stage.as_raw() as u64))        .src_access_mask(vk::AccessFlags2::from_raw(b.src_access_mask.as_raw() as u64))        .dst_access_mask(vk::AccessFlags2::from_raw(b.dst_access_mask.as_raw() as u64))        .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)        .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)        .old_layout(b.old_layout)        .new_layout(b.new_layout)        .image(b.image)        .subresource_range(b.subresource_range)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>RenderContext<\/code> \u0438 <code>RenderGraphExecutor<\/code> \u0431\u044b\u0441\u0442\u0440\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0431\u0435\u0440\u0443\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0430 <code>RenderGraph<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u043a\u0430\u0434\u0440. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c. \u041f\u043e\u043a\u0430\u0436\u0443 \u044d\u0442\u043e \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:  <\/p>\n<pre><code class=\"rust\">pub struct MotionBlurRenderer {    pipeline: Handle&lt;Pipeline&gt;,}impl MotionBlurRenderer {    pub fn new(executor: &amp;Arc&lt;RenderGraphExecutor&gt;) -&gt; Self {        let pipeline = executor.create_pipeline(            &amp;GraphicsPipelineDesc::new(\".\/simple.spv\", \".\/motion_blur.spv\")                .with_color(vk::Format::R8G8B8A8_UNORM)                .with_dynamic_scissor(true)                .with_dynamic_viewport(true)                .with_bindless(true)                .with_bindings(vec![                    BindingDesc {                        binding: 0,                        kind: BindingKind::SampledImage,                        stages: vk::ShaderStageFlags::FRAGMENT,                    },                    BindingDesc {                        binding: 1,                        kind: BindingKind::SampledImage,                        stages: vk::ShaderStageFlags::FRAGMENT,                    },                ]),        );        Self { pipeline }    }    pub fn render&lt;'a&gt;(        &amp;'a mut self,        rg: &amp;mut RenderGraph&lt;'a&gt;,        color_target: RgHandle&lt;Texture&gt;,        velocity_target: RgHandle&lt;Texture&gt;,    ) -&gt; RgHandle&lt;Texture&gt; {        let blurred_color = rg.create_texture(TextureDesc {            name: \"Pbr Color Blurred\",            format: Format::Explicit(vk::Format::R8G8B8A8_UNORM),            resolution: Resolution::FullRes,            usage: TextureUsage::ColorAttachmentSampled,        });        rg.add_pass(\"Motion Blur Pass\")            .color_attachment(                blurred_color,                vk_sync::AccessType::ColorAttachmentWrite,                vk::AttachmentLoadOp::CLEAR,                vk::AttachmentStoreOp::STORE,                vk::ClearColorValue {                    float32: [0.0, 0.0, 0.0, 0.0],                },            )            .read_texture(                color_target,                vk_sync::AccessType::FragmentShaderReadSampledImageOrUniformTexelBuffer,            )            .read_texture(                velocity_target,                vk_sync::AccessType::FragmentShaderReadSampledImageOrUniformTexelBuffer,            )            .execute(move |ctx| {                #[repr(C)]                #[derive(Clone, Copy, Pod, Zeroable, Debug)]                struct MotionBlurPush {                    sample_count: u32,                    max_velocity: f32,                    scale: f32,                }                ctx.bind_pipeline(self.pipeline, vk::PipelineBindPoint::GRAPHICS);                ctx.bind_bindless();                ctx.push_descriptor_texture(color_target, 2, 0);                ctx.push_descriptor_texture(velocity_target, 2, 1);                ctx.set_full_scissor();                ctx.set_full_viewport();                ctx.push_constants(&amp;MotionBlurPush {                    sample_count: 4,                    max_velocity: 0.01,                    scale: 0.1,                });                ctx.draw(3);            });        blurred_color    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0420\u0430\u0437\u043c\u0435\u0440 \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u043d\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u044d\u043a\u0440\u0430\u043d\u0430, \u0438 \u043b\u0438\u0448\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u0438\u043c \u0438\u0437 \u043d\u0438\u0445 \u043d\u0443\u0436\u0435\u043d \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440.<\/p>\n<p><em>Push descriptors<\/em> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441 \u0441\u0440\u0430\u0437\u0443, \u0431\u0435\u0437 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f descriptor set, \u043d\u043e \u0446\u0435\u043d\u043e\u0439 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 CPU.<\/p>\n<p><em>Bindless<\/em> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0430 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043d\u0438\u043c \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443, \u0447\u0442\u043e \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 CPU.<\/p>\n<p> \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0445\u043e\u0434 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c callback, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 <code>PassContext<\/code>. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043a\u043e\u043f\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 (<code>primary<\/code> \u0438\u043b\u0438 <code>secondary<\/code>) \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u0438\u0437 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. \u0412\u043e\u0442 \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430:  <\/p>\n<pre><code class=\"rust\">#[derive(Default)]pub struct RuntimeData {    pub current_layout: Option&lt;vk::PipelineLayout&gt;,    pub current_bind_point: Option&lt;vk::PipelineBindPoint&gt;,    pub descriptor_sets: Vec&lt;vk::DescriptorSet&gt;,}pub struct StaticData&lt;'a&gt; {    pub device: &amp;'a ash::Device,    pub push_descriptor: &amp;'a ash::khr::push_descriptor::Device,    pub resources: RenderResources,    pub extent: vk::Extent2D,    pub cmd: vk::CommandBuffer,}pub struct PassContext&lt;'a&gt; {    pub static_data: StaticData&lt;'a&gt;,    pub runtime_data: RuntimeData,}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p> \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0432\u0435\u0442\u043e\u0432 \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Vulkan, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0432\u044b\u0434\u0435\u043b\u0438\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f:  <\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0441\u043b\u043e\u043c\u0430\u043b \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 render loop, \u043f\u043e\u0447\u0438\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u0418\u043d\u0430\u0447\u0435 \u0432\u0435\u043b\u0438\u043a \u0440\u0438\u0441\u043a, \u0447\u0442\u043e \u0432\u0441\u0451 \u0437\u0430\u0442\u044f\u043d\u0435\u0442\u0441\u044f \u0438 \u0442\u044b \u0432 \u0438\u0442\u043e\u0433\u0435 \u0431\u0440\u043e\u0441\u0438\u0448\u044c \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0443\u0436\u0430\u0441\u0435\u043d. Vulkan \u043f\u043e\u0434\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0437\u043d\u0430\u043b\u0438 \u0434\u0440\u0443\u0433 \u043e \u0434\u0440\u0443\u0433\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0440\u0430\u0434\u0430\u0442\u044c. \u0421\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u0438 \u0434\u0435\u0442\u0430\u043b\u0438 \u043c\u043e\u0436\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u043b\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438, \u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u041a\u043e\u0441\u0442\u044b\u043b\u0438 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u043d\u0430\u0434\u043e\u043b\u0433\u043e.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 GPU, \u043e\u0442 Mali-G76 \u0434\u043e RTX 5090, \u0431\u0443\u0434\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u043e\u0439. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0442\u043e \u0436\u0435\u043b\u0435\u0437\u043e, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0448\u044c, \u0430 \u0437\u0430\u0442\u0435\u043c \u043b\u0438\u0431\u043e \u0434\u043e\u0431\u0430\u0432\u044c \u0432\u0442\u043e\u0440\u0443\u044e \u0432\u0435\u0442\u043a\u0443 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0436\u0435\u043b\u0435\u0437\u0430, \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043e\u0431\u0449\u0443\u044e \u043a\u043e\u0434\u043e\u0432\u0443\u044e \u0431\u0430\u0437\u0443, \u043b\u0438\u0431\u043e \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434.<\/p>\n<\/li>\n<li>\n<p>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u043b \u0442\u043e, \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0443\u0440\u0435\u0437\u0430\u043d\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0433\u0440\u0430\u0444\u0430, \u043d\u043e \u0434\u0430\u0436\u0435 \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e\u0435. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0434\u0432\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0435\u0445\u043d\u043e-\u0434\u0435\u043c\u043a\u0438 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0432\u0448\u0438\u0441\u044c \u0434\u0432\u0438\u0436\u043a\u043e\u043c <a href=\"https:\/\/github.com\/EmbarkStudios\/kajiya\" rel=\"noopener nofollow\">kajiya<\/a> \u043e\u0442 Embark <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/extt\/99\/0a\/10\/990a100b4d5c46f2e5e7757714f63ed2.gif\" alt=\"\u041f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0433\u0440\u0430\u0444\u0430 \u0438 \u0434\u0435\u043c\u043a\u0438(\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434)\" title=\"\u041f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0433\u0440\u0430\u0444\u0430 \u0438 \u0434\u0435\u043c\u043a\u0438(\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434)\" width=\"692\" height=\"388\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/extt\/99\/0a\/10\/990a100b4d5c46f2e5e7757714f63ed2.gif 780w,&#10;       https:\/\/habrastorage.org\/extt\/99\/0a\/10\/990a100b4d5c46f2e5e7757714f63ed2.gif 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0433\u0440\u0430\u0444\u0430 \u0438 \u0434\u0435\u043c\u043a\u0438(<a href=\"https:\/\/github.com\/olejaaaaaaaa\/delivery\" rel=\"noopener nofollow\">\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434<\/a>)<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/extt\/a3\/18\/19\/a31819b1cdec12880c0182c1ca007bc1.gif\" alt=\"\u0414\u0435\u043c\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043d\u0430 \u0433\u0440\u0430\u0444\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435(\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434)\" title=\"\u0414\u0435\u043c\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043d\u0430 \u0433\u0440\u0430\u0444\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435(\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434)\" width=\"692\" height=\"388\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/extt\/a3\/18\/19\/a31819b1cdec12880c0182c1ca007bc1.gif 780w,&#10;       https:\/\/habrastorage.org\/extt\/a3\/18\/19\/a31819b1cdec12880c0182c1ca007bc1.gif 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0435\u043c\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043d\u0430 \u0433\u0440\u0430\u0444\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435(\u0417\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043e\u0434)<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<p>\u0413\u0440\u0430\u0444 \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0432\u0438\u0436\u043a\u0430 Kajiya: <a href=\"https:\/\/github.com\/EmbarkStudios\/kajiya\/tree\/main\/crates\/lib\/kajiya-rg\" rel=\"noopener nofollow\">https:\/\/github.com\/EmbarkStudios\/kajiya\/tree\/main\/crates\/lib\/kajiya-rg<\/a><\/p>\n<p>\u041e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0433\u0440\u0430\u0444\u0430 \u043a\u0430\u043a \u0443 Frostbite \u043d\u0430 C++ \u0438 OpenGL: <a href=\"https:\/\/github.com\/skaarj1989\/FrameGraph\" rel=\"noopener nofollow\">https:\/\/github.com\/skaarj1989\/FrameGraph<\/a><\/p>\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u043e\u0442 Traverse Research \u043e\u0431 \u0438\u0445 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u043c \u0433\u0440\u0430\u0444\u0435: <a href=\"https:\/\/blog.traverseresearch.nl\/render-graph-101-f42646255636\" rel=\"noopener nofollow\">https:\/\/blog.traverseresearch.nl\/render-graph-101-f42646255636<\/a><\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1097618\/\">https:\/\/habr.com\/ru\/articles\/1097618\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412 \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0442\u0435\u043c, \u043a\u0442\u043e \u0443\u0436\u0435 \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0441\u0432\u043e\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u044b \u043d\u0430 Vulkan. \u042f \u043b\u0438\u0448\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 Vulkan-\u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.\u041a\u0430\u0436\u0434\u044b\u0439, \u043a\u0442\u043e \u0438\u043c\u0435\u0435\u0442 \u0445\u043e\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Vulkan, \u0437\u0430\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c. \u041a\u0430\u043a\u0438\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c? \u041a\u0430\u043a\u0438\u0435 \u0444\u0438\u0447\u0438 GPU \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438, \u0430 \u043a\u0430\u043a\u0438\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438? \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435? \u0410 \u0435\u0449\u0435 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0438 async compute&#8230;\u0421\u0430\u043c\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 &#8212; \u0442\u043e, \u0447\u0442\u043e GPU \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0437\u043d\u044b\u0435 (IMR vs TBDR, UMA vs Discrete). \u041a\u043e\u0433\u0434\u0430 \u043f\u044b\u0442\u0430\u0435\u0448\u044c\u0441\u044f \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u043e\u0434\u043d\u0438\u043c API \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0435\u0433\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0448\u044c \u043a \u0432\u0435\u0442\u043a\u0430\u043c, \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0432\u0435\u0442\u043a\u0430\u043c \u043a\u043e\u0434\u0430.Vulkan 1.3 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0438, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u041f\u041a, \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043c \u043a\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u0431\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0441 \u043d\u0435\u0433\u043e. \u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 GPU \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0441\u0435 \u043c\u0435\u043d\u044c\u0448\u0435, \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u041f\u041a-\u0440\u0435\u043d\u0434\u0435\u0440 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u043c\u0438 (\u0430 \u0442\u043e \u0438 \u0431\u0435\u0437 \u043d\u0438\u0445) \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445.\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0436\u0435 \u0434\u043e\u0439\u0442\u0438 \u0434\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430, \u044f \u0432\u0437\u044f\u043b \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u043f\u0440\u043e\u0444\u0438\u043b\u044c VP_LUNARG_desktop_baseline_2024 \u0438 \u0431\u0440\u0430\u043b \u043e\u0442\u0442\u0443\u0434\u0430 \u0432\u0441\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043b\u0438\u043c\u0438\u0442\u043e\u0432, \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0438 \u0444\u0438\u0447. \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e GPU \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439, \u0445\u043e\u0442\u044f \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u043b\u0438\u043c\u0438\u0442\u044b, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b\u0448\u0435.\u0418\u0437-\u0437\u0430 \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u0438 Vulkan \u0438 \u043e\u0431\u044a\u0435\u043c\u0430 \u0442\u0435\u043c\u044b \u0434\u0430\u043b\u044c\u0448\u0435 \u044f \u043e\u043f\u0438\u0448\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u044b\u0435 \u0432\u0430\u0436\u043d\u044b\u0435 \u043f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e \u0432\u0435\u0449\u0438, \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u0430 \u0438\u0434\u0435\u044f:pub struct RenderContext {    pub(crate) size_dependent: RwLock&lt;SizeDependentResources&gt;,    pub(crate) device: Device,    pub(crate) surface: Surface,    pub(crate) instance: Instance,}impl RenderContext {    pub fn new(window: &amp;Window) -&gt; Arc&lt;Self&gt; {        let instance = Instance::new();        let surface = Surface::new(&amp;instance, window);        let device = Device::new(&amp;instance, &amp;surface);        let size_dependent = RwLock::new(            SizeDependentResources::new(&amp;instance, &amp;surface, &amp;device)        );        Arc::new(Self {            size_dependent,            device,            surface,            instance,        })    }}\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 RenderContext (\u043e\u043d\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a Arc&lt;RenderContext&gt;) \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0438 \u0445\u0440\u0430\u043d\u0438\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 Vulkan-\u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: device, queue \u0438 GPU-\u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b. \u042f \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043b\u043e\u0436\u0438\u043b \u0432 \u043d\u0435\u0435 Send \u0438 Sync, \u0445\u043e\u0442\u044f \u0431\u044b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b glTF-\u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043d\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439. \u0427\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044f \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435 \u0437\u043d\u0430\u044e, \u0441\u0442\u043e\u0438\u043b\u043e \u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0438\u043b\u0438 \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u0440\u043e\u0449\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0443\u0436\u0435 \u0438\u043c\u0435\u044f \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0435\u0440.\u0417\u0430\u0442\u0435\u043c \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u00ab\u0433\u043e\u043b\u044b\u0435\u00bb vk-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 Handle. Handle &#8212; \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430-\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0434\u0430\u0432\u043d\u043e \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 crate &#8212; slotmap. Handle-based \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u0434\u043e\u043a\u043b\u0430\u0434\u0435 Frostbite \u043d\u0430 GDC, \u00abFrameGraph: Extensible Rendering Architecture in Frostbite\u00bb: \u0442\u0430\u043c \u043b\u044e\u0431\u043e\u0439 \u0440\u0435\u0441\u0443\u0440\u0441 &#8212; \u043b\u0438\u0448\u044c \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 (idResource), \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 FrameGraph. \u042f \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u0442\u0430\u043a \u0436\u0435 \u0438 \u0434\u043b\u044f \u0434\u043e\u043b\u0433\u043e\u0436\u0438\u0432\u0443\u0449\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0438 \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.#[derive(Clone)]pub struct RenderResources {    pub persistent: Arc&lt;ResourcePool&gt;,    pub transient: Arc&lt;TransientResourceCache&gt;,    pub bindless: Arc&lt;Bindless&gt;,}impl RenderResources {    pub fn new(ctx: &amp;Arc&lt;RenderContext&gt;) -&gt; Self {        Self {            bindless: Bindless::new(ctx),            persistent: ResourcePool::new(ctx),            transient: TransientResourceCache::new(),        }    }}pub struct RenderGraphExecutor {    pub ctx: Arc&lt;RenderContext&gt;,    resources: RenderResources,}impl RenderGraphExecutor {    pub fn new(window: &amp;winit::window::Window) -&gt; Arc&lt;Self&gt; {        let ctx = RenderContext::new(window);        Arc::new(Self {            resources: RenderResources::new(&amp;ctx),            ctx,        })    }    pub fn create_render_graph(&amp;self) -&gt; RenderGraph&lt;&#8216;_&gt; {        RenderGraph {            transient_cache: self.resources.transient.clone(),            passes: vec![],            _marker: PhantomData,        }    }    pub fn resize(&amp;self, width: u32, height: u32) {        self.ctx.resize(width, height);        self.resources.transient.invalid_cache();    }    pub fn create_texture(&amp;self, desc: &amp;TextureDesc, data: Option&lt;&amp;[u8]&gt;) -&gt; Handle&lt;Texture&gt; {        self.resources            .persistent            .create_texture(&amp;self.ctx, desc, data)    }    pub fn register_bindless_texture(&amp;self, handle: Handle&lt;Texture&gt;) -&gt; u32 {        let texture = self.resources.persistent.get_texture(handle);        self.resources            .bindless            .bind_image_view(&amp;self.ctx, texture.view)            .unwrap()    }   pub fn swapchain_texture(&amp;self) -&gt; Handle&lt;Texture&gt; {        self.resources.persistent.swapchain_texture()    }    pub fn execute(self: &amp;Arc&lt;Self&gt;, rg: &amp;mut RenderGraph&lt;&#8216;_&gt;) {        &#8230;    }    \/\/ \u0418 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b}pub struct Texture {    pub image: vk::Image,    pub allocation: Option&lt;Allocation&gt;,    pub view: vk::ImageView,    pub extent: vk::Extent2D,    pub aspect_mask: vk::ImageAspectFlags,}\u0418 \u0434\u0430, \u044f \u043d\u0435 \u043a\u043b\u043e\u043d\u0443\u044e vk::Device \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0443 \u043c\u0435\u043d\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 SlotMap&lt;Id, vk::*&gt;. \u0414\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u0430 \u0431\u044b\u043b\u0430 \u0431\u044b \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u043e\u043c \u043a\u0430\u0434\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0431\u044b, \u0447\u0442\u043e \u0440\u0435\u0441\u0443\u0440\u0441 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043d\u043e \u044f \u0435\u0435 \u0442\u0430\u043a \u0438 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0438 \u043f\u043e\u0447\u0442\u0438 \u043d\u0435 \u0443\u0434\u0435\u043b\u044f\u043b \u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f.RenderResources \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c Clone, Send \u0438 Sync: \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f PassContext, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435.\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u0430\u0434\u0440 RenderGraphExecutor \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 RenderGraph, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043f\u0440\u043e\u0445\u043e\u0434\u0430\u0445 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u0442 \u043a\u0435\u0448 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 (transient) \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0440\u0435\u0447\u044c \u0441\u0435\u0431\u044f \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 Handle \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u0430\u0434\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0441\u0435\u043a\u0443\u0442\u0441\u044f.\u0424\u0443\u043d\u043a\u0446\u0438\u044f execute \u043e\u0434\u043d\u0438\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u044b\u0432\u043e\u0434 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d. \u041e\u043d\u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0432\u043c\u0435\u0449\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c compile \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0431\u0430\u0440\u044c\u0435\u0440\u044b \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.Swapchain Texture &#8212; \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0439 Handle, \u043d\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u044b\u0439. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a Handle \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0443\u044e \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0443 resolve(), \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f: \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e \u0438\u043d\u0434\u0435\u043a\u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 acquire_next_image(), \u0431\u0435\u0440\u0443 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 image \u0438 view \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u0435\u0436\u043d\u0438\u0445. \u041a\u043e\u0434 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0443\u0436\u0430\u0441\u043d\u043e, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:{    let backbuffer = self.resources.persistent.swapchain_texture();    let mut resources = self.resources.persistent.inner.write();    let new_image = frame.swapchain_images[image_index as usize];    let texture = resources.textures.get_mut(backbuffer.id).unwrap();    texture.image = new_image;    texture.view = frame.swapchain_image_views[image_index as usize];    resources        .image_access        .entry(new_image)        .or_insert(AccessType::Nothing);}RenderGraph &#8212; \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043a\u0430\u0434\u0440\u0435: \u043f\u0440\u043e\u0445\u043e\u0434\u044b \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0420\u0435\u0441\u0443\u0440\u0441\u044b \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430 \u0442\u0440\u0438 \u0432\u0438\u0434\u0430: \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0435 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435. \u0427\u0442\u043e\u0431\u044b \u0438\u0445 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0442\u0438\u043f\u043e\u0432, \u044f \u0432\u0432\u0435\u043b RgHandle&lt;T&gt; \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 ExportHandle&lt;T&gt; \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0445; \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0435 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443\u044e\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c Handle.  pub struct RenderGraph&lt;&#8216;a&gt; {    pub passes: Vec&lt;Pass&lt;&#8216;a&gt;&gt;,    pub transient_cache: Arc&lt;TransientResourceCache&gt;,    pub _marker: PhantomData&lt;*mut ()&gt;,}impl&lt;&#8216;a&gt; RenderGraph&lt;&#8216;a&gt; {    pub fn new(cache: Arc&lt;TransientResourceCache&gt;) -&gt; Self {        Self {            transient_cache: cache,            passes: vec![],            _marker: PhantomData,        }    }    pub fn add_pass&lt;S: Into&lt;String&gt;&gt;(&amp;mut self, name: S) -&gt; PassBuilder&lt;&#8216;_, &#8216;a&gt; {        PassBuilder::new(self, name.into())    }    pub fn import_texture(&amp;mut self, handle: Handle&lt;Texture&gt;) -&gt; RgHandle&lt;Texture&gt; {        self.transient_cache.import_texture(handle)    }    pub fn export_texture(        &amp;mut self,        handle: RgHandle&lt;Texture&gt;,        final_access: vk_sync::AccessType,    ) -&gt; ExportHandle&lt;Texture&gt; {        self.transient_cache.export_texture(handle, final_access)    }    pub fn import_buffer(&amp;mut self, handle: Handle&lt;Buffer&gt;) -&gt; RgHandle&lt;Buffer&gt; {        self.transient_cache.import_buffer(handle)    }    \/\/ \u0414\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b&#8230;}\u0414\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0445\u043e\u0434 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0443, \u044f \u0432\u0437\u044f\u043b AccessType \u0438\u0437 vk-sync \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e.\u041a\u0435\u0448 \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 \u0441\u0430\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043a\u0430\u0434\u0440\u0430\u0445. \u041f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u043e\u043d\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c\u0438.\u0412 \u043f\u0430\u0441\u0441\u0430\u0445 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0445 \u0438 \u043f\u0438\u0448\u0443\u0448\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445. \u0422\u0438\u043f \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u0438\u043c\u044f \u043f\u0430\u0441\u0441\u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043f\u043e\u043a\u0430 \u0447\u0442\u043e. \u0412\u043e\u0442 \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442:#[derive(PartialEq)]pub enum QueueType {    Compute,    Transfer,    Graphics,}pub enum DependencyResource {    ColorAttachment {        handle: RgHandle&lt;Texture&gt;,        load: vk::AttachmentLoadOp,        store: vk::AttachmentStoreOp,        clear_value: vk::ClearColorValue,    },    DepthAttachment {        handle: RgHandle&lt;Texture&gt;,        load: vk::AttachmentLoadOp,        store: vk::AttachmentStoreOp,        clear_value: vk::ClearDepthStencilValue,    },    Buffer(RgHandle&lt;Buffer&gt;),    Texture(RgHandle&lt;Texture&gt;),}pub struct Pass&lt;&#8216;a&gt; {    pub name: String,    pub queue_type: QueueType,    pub reads: Vec&lt;(DependencyResource, AccessType)&gt;,    pub writes: Vec&lt;(DependencyResource, AccessType)&gt;,    pub callback: Box&lt;dyn Fn(&amp;mut PassContext) + &#8216;a&gt;,}pub struct PassBuilder&lt;&#8216;b, &#8216;a&gt; {    name: String,    queue_type: QueueType,    reads: Vec&lt;(DependencyResource, AccessType)&gt;,    writes: Vec&lt;(DependencyResource, AccessType)&gt;,    rg: &amp;&#8217;b mut RenderGraph&lt;&#8216;a&gt;,}\u0412 execute \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043b\u0438\u0448\u044c:\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-499690","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/499690","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=499690"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/499690\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=499690"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=499690"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=499690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}