You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
learn-wgpu/showcase/windowless/index.html

203 lines
54 KiB
HTML

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Wgpu without a window | Learn Wgpu</title>
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2020-08-12T22:11:10.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Wgpu without a window"><meta property="og:type" content="website"><meta property="og:url" content="/showcase/windowless/"><meta name="twitter:title" content="Wgpu without a window"><meta name="twitter:url" content="/showcase/windowless/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin R Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.7acc6ef6.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.c3952c3b.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/2.da3fd46f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/21.e1893fb6.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/22.2132e362.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/10.de8cadfb.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.c7578bf2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.81336113.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.de363f88.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.f852c057.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.9e24e3cf.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.c7356fb1.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.8d0c6c00.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.bd274f60.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.1095b69a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.70e640cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.1a88f225.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6da05868.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.4449a1a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.5b0dad74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.04f788d9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.a3ac06e2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.281013fa.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.94d0aff7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.dc887be9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/4.1a5062fd.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.543d7edb.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.36948d15.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.3b9d8029.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.cffb95fd.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.ecb6e79c.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.7acc6ef6.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-swapchain/" class="sidebar-link">The Swapchain</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" class="sidebar-link">Foreward</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="active sidebar-link">Wgpu without a window</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/windowless/#so-what-do-we-need-to-do" class="sidebar-link">So what do we need to do?</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/windowless/#a-triangle-without-a-window" class="sidebar-link">A triangle without a window</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/windowless/#getting-data-out-of-a-buffer" class="sidebar-link">Getting data out of a buffer</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/windowless/#main-is-not-asyncable" class="sidebar-link">Main is not asyncable</a></li></ul></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><a href="/learn-wgpu/showcase/alignment/" class="sidebar-link">Memory Layout in GLSL</a></li><li><a href="/learn-wgpu/showcase/imgui-demo/" class="sidebar-link">Basic Imgui Demo</a></li></ul></section></li><li><a href="/learn-wgpu/news/" class="sidebar-link">News</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="wgpu-without-a-window"><a href="#wgpu-without-a-window" class="header-anchor">#</a> Wgpu without a window</h1> <p>Sometimes we just want to leverage the gpu. Maybe we want to crunch a large set of numbers in parallel. Maybe we're working on a 3D movie, and need to create a realistic looking scene with path tracing. Maybe we're mining a cryptocurrency. In all these situations, we don't necessarily <em>need</em> to see what's going on.</p> <h2 id="so-what-do-we-need-to-do"><a href="#so-what-do-we-need-to-do" class="header-anchor">#</a> So what do we need to do?</h2> <p>It's actually quite simple. We don't <em>need</em> a window to create an <code>Instance</code>, we don't <em>need</em> a window to select an <code>Adapter</code>, nor do we <em>need</em> a window to create a <code>Device</code>. We only needed the window to create a <code>Surface</code> which we needed to create the <code>SwapChain</code>. Once we have a <code>Device</code>, we have all we need to start sending commands to the gpu.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> adapter <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Adapter</span><span class="token punctuation">::</span><span class="token function">request</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RequestAdapterOptions</span> <span class="token punctuation">{</span>
power_preference<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">PowerPreference</span><span class="token punctuation">::</span><span class="token class-name">Default</span><span class="token punctuation">,</span>
compatible_surface<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BackendBit</span><span class="token punctuation">::</span><span class="token constant">PRIMARY</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token punctuation">(</span>device<span class="token punctuation">,</span> queue<span class="token punctuation">)</span> <span class="token operator">=</span> adapter<span class="token punctuation">.</span><span class="token function">request_device</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token class-name">Default</span><span class="token punctuation">::</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="a-triangle-without-a-window"><a href="#a-triangle-without-a-window" class="header-anchor">#</a> A triangle without a window</h2> <p>Now we've talked about not needing to see what the gpu is doing, but we do need to see the results at some point. If we look back to talking about the <a href="/learn-wgpu/beginner/tutorial2-swapchain/#render">swap chain</a> we see that we use <code>swap_chain.get_next_texture()</code> to grab a texture to draw to. We'll skip that step by creating the texture ourselves. One thing to note here is we need to specify <code>wgpu::TextureFormat::Rgba8UnormSrgb</code> to <code>format</code> instead of <code>wgpu::TextureFormat::Bgra8UnormSrgb</code> since PNG uses RGBA, not BGRA.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> texture_size <span class="token operator">=</span> <span class="token number">256u32</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> texture_desc <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">TextureDescriptor</span> <span class="token punctuation">{</span>
size<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Extent3d</span> <span class="token punctuation">{</span>
width<span class="token punctuation">:</span> texture_size<span class="token punctuation">,</span>
height<span class="token punctuation">:</span> texture_size<span class="token punctuation">,</span>
depth<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
array_layer_count<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
mip_level_count<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
sample_count<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
dimension<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">TextureDimension</span><span class="token punctuation">::</span><span class="token constant">D2</span><span class="token punctuation">,</span>
format<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">TextureFormat</span><span class="token punctuation">::</span><span class="token class-name">Rgba8UnormSrgb</span><span class="token punctuation">,</span>
usage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">TextureUsage</span><span class="token punctuation">::</span><span class="token constant">COPY_SRC</span>
<span class="token operator">|</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">TextureUsage</span><span class="token punctuation">::</span><span class="token constant">OUTPUT_ATTACHMENT</span>
<span class="token punctuation">,</span>
label<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> texture <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_texture</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>texture_desc<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> texture_view <span class="token operator">=</span> texture<span class="token punctuation">.</span><span class="token function">create_default_view</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>We're using <code>TextureUsage::OUTPUT_ATTACHMENT</code> so wgpu can render to our texture. The <code>TextureUsage::COPY_SRC</code> is so we can pull data out of the texture so we can save it to a file.</p> <p>While we can use this texture to draw our triangle, we need some way to get at the pixels inside it. Back in the <a href="/learn-wgpu/beginner/tutorial5-textures/">texture tutorial</a> we used a buffer load color data from a file that we then copied into our buffer. Now we are going to do the reverse: copy data into a buffer from our texture to save into a file. We'll need a buffer big enough for our data.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// we need to store this for later</span>
<span class="token keyword">let</span> u32_size <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>mem<span class="token punctuation">::</span></span><span class="token function">size_of</span><span class="token punctuation">::</span><span class="token operator">&lt;</span><span class="token keyword">u32</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token keyword">u32</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> output_buffer_size <span class="token operator">=</span> <span class="token punctuation">(</span>u32_size <span class="token operator">*</span> texture_size <span class="token operator">*</span> texture_size<span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferAddress</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> output_buffer_desc <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferDescriptor</span> <span class="token punctuation">{</span>
size<span class="token punctuation">:</span> output_buffer_size<span class="token punctuation">,</span>
usage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferUsage</span><span class="token punctuation">::</span><span class="token constant">COPY_DST</span>
<span class="token comment">// this tells wpgu that we want to read this buffer from the cpu</span>
<span class="token operator">|</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferUsage</span><span class="token punctuation">::</span><span class="token constant">MAP_READ</span><span class="token punctuation">,</span>
label<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> output_buffer <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_buffer</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>output_buffer_desc<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Now that we have something to draw to, let's make something to draw. Since we're just drawing a triangle, let's grab the shader code from the <a href="/learn-wgpu/beginner/tutorial3-pipeline/#writing-the-shaders">pipeline tutorial</a>.</p> <div class="language-glsl extra-class"><pre class="language-glsl"><code><span class="token comment">// shader.vert</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">version</span> <span class="token expression"><span class="token number">450</span></span></span>
<span class="token keyword">const</span> <span class="token keyword">vec2</span> positions<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">vec2</span><span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">(</span>
<span class="token keyword">vec2</span><span class="token punctuation">(</span><span class="token number">0.0</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token keyword">vec2</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">0.5</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token keyword">vec2</span><span class="token punctuation">(</span><span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">0.5</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
gl_Position <span class="token operator">=</span> <span class="token keyword">vec4</span><span class="token punctuation">(</span>positions<span class="token punctuation">[</span>gl_VertexIndex<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">0.0</span><span class="token punctuation">,</span> <span class="token number">1.0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="language-glsl extra-class"><pre class="language-glsl"><code><span class="token comment">// shader.frag</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">version</span> <span class="token expression"><span class="token number">450</span></span></span>
<span class="token keyword">layout</span><span class="token punctuation">(</span>location<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">out</span> <span class="token keyword">vec4</span> f_color<span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
f_color <span class="token operator">=</span> <span class="token keyword">vec4</span><span class="token punctuation">(</span><span class="token number">0.3</span><span class="token punctuation">,</span> <span class="token number">0.2</span><span class="token punctuation">,</span> <span class="token number">0.1</span><span class="token punctuation">,</span> <span class="token number">1.0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Using that we'll create a simple <code>RenderPipeline</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> vs_src <span class="token operator">=</span> <span class="token macro property">include_str!</span><span class="token punctuation">(</span><span class="token string">&quot;shader.vert&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> fs_src <span class="token operator">=</span> <span class="token macro property">include_str!</span><span class="token punctuation">(</span><span class="token string">&quot;shader.frag&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> compiler <span class="token operator">=</span> <span class="token namespace">shaderc<span class="token punctuation">::</span></span><span class="token class-name">Compiler</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> vs_spirv <span class="token operator">=</span> compiler<span class="token punctuation">.</span><span class="token function">compile_into_spirv</span><span class="token punctuation">(</span>vs_src<span class="token punctuation">,</span> <span class="token namespace">shaderc<span class="token punctuation">::</span></span><span class="token class-name">ShaderKind</span><span class="token punctuation">::</span><span class="token class-name">Vertex</span><span class="token punctuation">,</span> <span class="token string">&quot;shader.vert&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;main&quot;</span><span class="token punctuation">,</span> <span class="token class-name">None</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> fs_spirv <span class="token operator">=</span> compiler<span class="token punctuation">.</span><span class="token function">compile_into_spirv</span><span class="token punctuation">(</span>fs_src<span class="token punctuation">,</span> <span class="token namespace">shaderc<span class="token punctuation">::</span></span><span class="token class-name">ShaderKind</span><span class="token punctuation">::</span><span class="token class-name">Fragment</span><span class="token punctuation">,</span> <span class="token string">&quot;shader.frag&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;main&quot;</span><span class="token punctuation">,</span> <span class="token class-name">None</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> vs_data <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token function">read_spirv</span><span class="token punctuation">(</span><span class="token namespace">std<span class="token punctuation">::</span>io<span class="token punctuation">::</span></span><span class="token class-name">Cursor</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>vs_spirv<span class="token punctuation">.</span><span class="token function">as_binary_u8</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> fs_data <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token function">read_spirv</span><span class="token punctuation">(</span><span class="token namespace">std<span class="token punctuation">::</span>io<span class="token punctuation">::</span></span><span class="token class-name">Cursor</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>fs_spirv<span class="token punctuation">.</span><span class="token function">as_binary_u8</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> vs_module <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_shader_module</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>vs_data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> fs_module <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_shader_module</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>fs_data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> render_pipeline_layout <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_pipeline_layout</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">PipelineLayoutDescriptor</span> <span class="token punctuation">{</span>
bind_group_layouts<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> render_pipeline <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_render_pipeline</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RenderPipelineDescriptor</span> <span class="token punctuation">{</span>
layout<span class="token punctuation">:</span> <span class="token operator">&amp;</span>render_pipeline_layout<span class="token punctuation">,</span>
vertex_stage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ProgrammableStageDescriptor</span> <span class="token punctuation">{</span>
module<span class="token punctuation">:</span> <span class="token operator">&amp;</span>vs_module<span class="token punctuation">,</span>
entry_point<span class="token punctuation">:</span> <span class="token string">&quot;main&quot;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
fragment_stage<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ProgrammableStageDescriptor</span> <span class="token punctuation">{</span>
module<span class="token punctuation">:</span> <span class="token operator">&amp;</span>fs_module<span class="token punctuation">,</span>
entry_point<span class="token punctuation">:</span> <span class="token string">&quot;main&quot;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
rasterization_state<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RasterizationStateDescriptor</span> <span class="token punctuation">{</span>
front_face<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">FrontFace</span><span class="token punctuation">::</span><span class="token class-name">Ccw</span><span class="token punctuation">,</span>
cull_mode<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">CullMode</span><span class="token punctuation">::</span><span class="token class-name">Back</span><span class="token punctuation">,</span>
depth_bias<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
depth_bias_slope_scale<span class="token punctuation">:</span> <span class="token number">0.0</span><span class="token punctuation">,</span>
depth_bias_clamp<span class="token punctuation">:</span> <span class="token number">0.0</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
primitive_topology<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">PrimitiveTopology</span><span class="token punctuation">::</span><span class="token class-name">TriangleList</span><span class="token punctuation">,</span>
color_states<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ColorStateDescriptor</span> <span class="token punctuation">{</span>
format<span class="token punctuation">:</span> texture_desc<span class="token punctuation">.</span>format<span class="token punctuation">,</span>
color_blend<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BlendDescriptor</span><span class="token punctuation">::</span><span class="token constant">REPLACE</span><span class="token punctuation">,</span>
alpha_blend<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BlendDescriptor</span><span class="token punctuation">::</span><span class="token constant">REPLACE</span><span class="token punctuation">,</span>
write_mask<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ColorWrite</span><span class="token punctuation">::</span><span class="token constant">ALL</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
depth_stencil_state<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
vertex_state<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">VertexStateDescriptor</span> <span class="token punctuation">{</span>
index_format<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">IndexFormat</span><span class="token punctuation">::</span><span class="token class-name">Uint16</span><span class="token punctuation">,</span>
vertex_buffers<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
sample_count<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
sample_mask<span class="token punctuation">:</span> <span class="token operator">!</span><span class="token number">0</span><span class="token punctuation">,</span>
alpha_to_coverage_enabled<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>We're going to need an encoder, so let's do that.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> <span class="token keyword">mut</span> encoder <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_command_encoder</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">CommandEncoderDescriptor</span> <span class="token punctuation">{</span>
label<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>The <code>RenderPass</code> is where things get interesting. A render pass requires at least one color attachment. A color attachment requires a <code>TextureView</code> to attach to. We used to use a texture from <code>SwapChain</code> for this, but any <code>TextureView</code> will do, including our <code>texture_view</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token punctuation">{</span>
<span class="token keyword">let</span> render_pass_desc <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RenderPassDescriptor</span> <span class="token punctuation">{</span>
color_attachments<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RenderPassColorAttachmentDescriptor</span> <span class="token punctuation">{</span>
attachment<span class="token punctuation">:</span> <span class="token operator">&amp;</span>texture_view<span class="token punctuation">,</span>
resolve_target<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
load_op<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">LoadOp</span><span class="token punctuation">::</span><span class="token class-name">Clear</span><span class="token punctuation">,</span>
store_op<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">StoreOp</span><span class="token punctuation">::</span><span class="token class-name">Store</span><span class="token punctuation">,</span>
clear_color<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Color</span> <span class="token punctuation">{</span>
r<span class="token punctuation">:</span> <span class="token number">0.1</span><span class="token punctuation">,</span>
g<span class="token punctuation">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span>
b<span class="token punctuation">:</span> <span class="token number">0.3</span><span class="token punctuation">,</span>
a<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
depth_stencil_attachment<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> render_pass <span class="token operator">=</span> encoder<span class="token punctuation">.</span><span class="token function">begin_render_pass</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>render_pass_desc<span class="token punctuation">)</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">set_pipeline</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>render_pipeline<span class="token punctuation">)</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">draw</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">..</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">..</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>There's not much we can do with the data when it's stuck in a <code>Texture</code>, so let's copy it into our <code>output_buffer</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code>encoder<span class="token punctuation">.</span><span class="token function">copy_texture_to_buffer</span><span class="token punctuation">(</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">TextureCopyView</span> <span class="token punctuation">{</span>
texture<span class="token punctuation">:</span> <span class="token operator">&amp;</span>texture<span class="token punctuation">,</span>
mip_level<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
array_layer<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
origin<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Origin3d</span><span class="token punctuation">::</span><span class="token constant">ZERO</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferCopyView</span> <span class="token punctuation">{</span>
buffer<span class="token punctuation">:</span> <span class="token operator">&amp;</span>output_buffer<span class="token punctuation">,</span>
offset<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
bytes_per_row<span class="token punctuation">:</span> u32_size <span class="token operator">*</span> texture_size<span class="token punctuation">,</span>
rows_per_image<span class="token punctuation">:</span> texture_size<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
texture_desc<span class="token punctuation">.</span>size<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Now that we've made all our commands, let's submit them to the gpu.</p> <div class="language-rust extra-class"><pre class="language-rust"><code>device<span class="token punctuation">.</span><span class="token function">get_queue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">submit</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token punctuation">[</span>encoder<span class="token punctuation">.</span><span class="token function">finish</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="getting-data-out-of-a-buffer"><a href="#getting-data-out-of-a-buffer" class="header-anchor">#</a> Getting data out of a buffer</h2> <p>The <code>Buffer</code> struct has two methods to access it's contents: <code>map_read</code>, and <code>map_write</code>. Both of these methods take in a <code>BufferAddress</code> specifying the byte to start from, the size in bytes of the chunk we're reading/writing, and a callback lambda that where we'll actually access the data. We're going to use <code>map_read</code> to save our <code>output_buffer</code> to a png file.</p> <p>The actual mapping code is fairly simple.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// NOTE: We have to create the mapping THEN device.poll(). If we don't</span>
<span class="token comment">// the application will freeze.</span>
<span class="token keyword">let</span> mapping <span class="token operator">=</span> output_buffer<span class="token punctuation">.</span><span class="token function">map_read</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> output_buffer_size<span class="token punctuation">)</span><span class="token punctuation">;</span>
device<span class="token punctuation">.</span><span class="token function">poll</span><span class="token punctuation">(</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Maintain</span><span class="token punctuation">::</span><span class="token class-name">Wait</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> result <span class="token operator">=</span> mapping<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> data <span class="token operator">=</span> result<span class="token punctuation">.</span><span class="token function">as_slice</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">image<span class="token punctuation">::</span></span><span class="token punctuation">{</span><span class="token class-name">ImageBuffer</span><span class="token punctuation">,</span> <span class="token class-name">Rgba</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> buffer <span class="token operator">=</span> <span class="token class-name">ImageBuffer</span><span class="token punctuation">::</span><span class="token operator">&lt;</span><span class="token class-name">Rgba</span><span class="token operator">&lt;</span><span class="token keyword">u8</span><span class="token operator">&gt;</span><span class="token punctuation">,</span> _<span class="token operator">&gt;</span><span class="token punctuation">::</span><span class="token function">from_raw</span><span class="token punctuation">(</span>
texture_size<span class="token punctuation">,</span>
texture_size<span class="token punctuation">,</span>
data<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
buffer<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token string">&quot;image.png&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="main-is-not-asyncable"><a href="#main-is-not-asyncable" class="header-anchor">#</a> Main is not asyncable</h2> <p>The <code>main()</code> method can't return a future, so we can't use the <code>async</code> keyword. We'll get around this by putting our code into a different function so that we can block on it in <code>main()</code>. You'll need to use the <a href="https://docs.rs/futures" target="_blank" rel="noopener noreferrer">futures crate<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">async</span> <span class="token keyword">fn</span> <span class="token function-definition function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Windowless drawing code...</span>
<span class="token punctuation">}</span>
<span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">use</span> <span class="token namespace">futures<span class="token punctuation">::</span>executor<span class="token punctuation">::</span></span>block_on<span class="token punctuation">;</span>
<span class="token function">block_on</span><span class="token punctuation">(</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>With all that you should have an image like this.</p> <p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAFq0lEQVR4nO3U2XVcRxBEQcovOiJf5IY8kl8SRLAPAXAweEvvGfFRFlTeP/786+9/vwGRBACCCQAEEwAIJgAQTAAgmABAMAGAYAIAwQQAggkABBMACCYAEEwAIJgAQDABgGACAMEEAIIJAAQTAAgmABBMACCYAEAwAYBgAgDBBACCCQAEEwAIJgAQTAAgmABAMAGAYAIAwQQAggkABBMACCYAEEwAIJgAQDABgGACAMEEAIIJAAQTAAgmABBMACCYAEAwAYBgAgDBBACCCQAEEwAIJgAQTAAgmABAMAGAYAIAwQQAggkABBMACCYAEEwAIJgAQDABgGACAMEEINj3b/+83G8v9/vLJZEABBMABCBUGX8hApkEIJQA8D8BCPRx/IUI5BGAQAJAIQBhPht/IQJZBCCMAPCWAAT5avyFCOQQgCACwEcCEOLo+AsRyCAAIQSARwQgwNnxFyKwPwEIIAB8RgA2d3X8hQjsTQA2JwA8IwAbuzv+QgT2JQAbEwC+IgCbqjX+QgT2JACbEgCOEIAN1R5/IQL7EYANCQBHCcBmWo2/EIG9CMBmBIAzBGAjrcdfiMA+BGAjAsBZArCJXuMvRGAPArAJAeAKAdhA7/EXIrA+AdiAAHCVACxu1PgLEVibACxOALhDABY2evyFCKxLABYmANwlAIuaZfyFCKxJABYlANQgAAuabfyFCKxHABYkANQiAIuZdfyFCKxFABYjANQkAAuZffyFCKxDABYiANQmAItYZfyFCKxBABYhALQgAAtYbfyFCMxPABYgALQiAJNbdfyFCMxNACYnALQkABNbffyFCMxLACYmALQmAJPaZfyFCMxJACYlAPQgABPabfyFCMxHACYkAPQiAJPZdfyFCMxFACYjAPQkABPZffyFCMxDACYiAPQmAJNIGX8hAnMQgEkIACMIwATSxl+IwHgCMAEBYBQBGCx1/IUIjCUAgwmAAIwkAAOlj78QgXEEYCABeCUA4wjAIMb/ngiMIQCDCMB7AjCGAAxg/I+JQH8CMIAAPCYA/QlAZ8b/nAj0JQCdCcBzAtCXAHRk/MeIQD8C0JEAHCMA/QhAJ8Z/jgj0IQCdCMA5AtCHAHRg/NeIQHsC0IEAXCMA7QlAY8Z/jwi0JQCNCcA9AtCWADRk/HWIQDsC0JAA1CEA7QhAI8Zflwi0IQCNCEBdAtCGADRg/G2IQH0C0IAAtCEA9QlAZcbflgjUJQCVCUBbAlCXAFRk/H2IQD0CUJEA9CEA9QhAJcbflwjUIQCVCEBfAlCHAFRg/GOIwH0CUIEAjCEA9wnATcY/lgjcIwA3CcBYAnCPANxg/HMQgesE4AYBmIMAXCcAFxn/XETgGgG4SADmIgDXCMAFxj8nEThPAC4QgDkJwHkCcJLxz00EzhGAkwRgbgJwjgCcYPxrEIHjBOAEAViDABwnAAcZ/1pE4BgBOEgA1iIAxwjAAca/JhH4mgAcIABrEoCvCcAXjH9tIvCcAHxBANYmAM8JwBPGvwcR+JwAPCEAexCAzwnAJ4x/LyLwmAB8QgD2IgCPCcADxr8nEfidADwgAHsSgN8JwAfGvzcReE8APhCAvQnAewLwhvFnEIFfBOANAcggAL8IwE/Gn0UEXgnATwKQRQBeCcAL488kAgLwgwBkEgABeHkB40+WHoH4AEAyAYBgAgDBBACCCQAEEwAIJgAQTAAgmABAMAGAYAIAwQQAggkABBMACCYAEEwAIJgAQDABgGACAMEEAIIJAAQTAAgmABBMACCYAEAwAYBgAgDBBACCCQAEEwAIJgAQTAAgmABAMAGAYAIAwQQAggkABBMACCYAEEwAIJgAQDABgGACAMEEAIIJAAQTAAgmABBMACCYAEAwAYBgAgDBBACCCQAEEwAIJgAQTAAgmABAMAGAYAIAwQQAggkABBMACCYAEEwAINh/p/JoLhfYRNsAAAAASUVORK5CYII=" alt="a brown triangle"></p> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/windowless/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">8/12/2020, 10:11:10 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/showcase/" class="prev router-link-active">
Foreward
</a></span> <span class="next"><a href="/learn-wgpu/showcase/gifs/">
Creating gifs
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.c3952c3b.js" defer></script><script src="/learn-wgpu/assets/js/2.da3fd46f.js" defer></script><script src="/learn-wgpu/assets/js/21.e1893fb6.js" defer></script><script src="/learn-wgpu/assets/js/22.2132e362.js" defer></script>
</body>
</html>