mirror of
https://github.com/sotrh/learn-wgpu.git
synced 2024-11-08 07:10:33 +00:00
261 lines
79 KiB
HTML
261 lines
79 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en-US">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>The Pipeline | Learn Wgpu</title>
|
|
<meta name="description" content="">
|
|
<meta name="generator" content="VuePress 1.4.0">
|
|
|
|
<meta property="article:modified_time" content="2021-02-19T03:56:47.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="The Pipeline"><meta property="og:type" content="website"><meta property="og:url" content="/beginner/tutorial3-pipeline/"><meta name="twitter:title" content="The Pipeline"><meta name="twitter:url" content="/beginner/tutorial3-pipeline/"><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.6593075e.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/2.da3fd46f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/12.26aabcb1.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.65c8dcc2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.78eedf26.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.f852c057.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.0fda50ec.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.f1c9d31a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.8d0c6c00.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.d3691f26.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.e9350ae9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.70e640cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.19d2890c.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.2c8435d6.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.2a393c66.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.dc887be9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/4.6b1a77da.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.6c35427e.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.7f771450.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88810c81.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.d5139107.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 open"><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="active sidebar-link">The Pipeline</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#what-s-a-pipeline" class="sidebar-link">What's a pipeline?</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#wait-shaders" class="sidebar-link">Wait shaders?</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#vertex-fragment-what-are-those" class="sidebar-link">Vertex, fragment.. what are those?</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#glsl-and-spir-v" class="sidebar-link">GLSL and SPIR-V</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#writing-the-shaders" class="sidebar-link">Writing the shaders</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#how-do-we-use-the-shaders" class="sidebar-link">How do we use the shaders?</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#using-a-pipeline" class="sidebar-link">Using a pipeline</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#compiling-shaders-and-include-spirv" class="sidebar-link">Compiling shaders and include_spirv</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial3-pipeline/#challenge" class="sidebar-link">Challenge</a></li></ul></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"><span>Showcase</span> <span class="arrow right"></span></p> <!----></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="the-pipeline"><a href="#the-pipeline" class="header-anchor">#</a> The Pipeline</h1> <h2 id="what-s-a-pipeline"><a href="#what-s-a-pipeline" class="header-anchor">#</a> What's a pipeline?</h2> <p>If you're familiar with OpenGL, you may remember using shader programs. You can think of a pipeline as a more robust version of that. A pipeline describes all the actions the gpu will preform when acting on a set of data. In this section, we will be creating a <code>RenderPipeline</code> specifically.</p> <h2 id="wait-shaders"><a href="#wait-shaders" class="header-anchor">#</a> Wait shaders?</h2> <p>Shaders are mini programs that you send to the gpu to perform operations on your data. There are 3 main types of shader: vertex, fragment, and compute. There are others such as geometry shaders, but they're more of an advanced topic. For now we're just going to use vertex, and fragment shaders.</p> <h2 id="vertex-fragment-what-are-those"><a href="#vertex-fragment-what-are-those" class="header-anchor">#</a> Vertex, fragment.. what are those?</h2> <p>A vertex is a point in 3d space (can also be 2d). These vertices are then bundled in groups of 2s to form lines and/or 3s to form triangles.</p> <img src="/learn-wgpu/assets/img/tutorial3-pipeline-vertices.5e39e8fc.png"> <p>Most modern rendering uses triangles to make all shapes, from simple shapes (such as cubes), to complex ones (such as people). These triangles are stored as vertices which are the points that make up the corners of the triangles.</p> <p>We use a vertex shader to manipulate the vertices, in order to transform the shape to look the way we want it.</p> <p>The vertices are then converted into fragments. Every pixel in the result image gets at least one fragment. Each fragment has a color that will be copied to its corresponding pixel. The fragment shader decides what color the fragment will be.</p> <h2 id="glsl-and-spir-v"><a href="#glsl-and-spir-v" class="header-anchor">#</a> GLSL and SPIR-V</h2> <p>Shaders in <code>wgpu</code> are written with a binary language called <a href="https://www.khronos.org/registry/spir-v/" target="_blank" rel="noopener noreferrer">SPIR-V<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>. SPIR-V is designed for computers to read, not people, so we're going to use a language called GLSL (specifically, with <code>wgpu</code> we need to use the <a href="https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_vulkan_glsl.txt" target="_blank" rel="noopener noreferrer">Vulkan flavor of GLSL<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>) to write our code, and then convert that to SPIR-V.</p> <p>In order to do that, we're going to need something to do the conversion. Add the following crate to your dependencies.</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">dependencies</span><span class="token punctuation">]</span>
|
|
<span class="token comment"># ...</span>
|
|
<span class="token key property">shaderc</span> <span class="token punctuation">=</span> <span class="token string">"0.7"</span>
|
|
</code></pre></div><p>We'll use this in a bit, but first let's create the shaders.</p> <h2 id="writing-the-shaders"><a href="#writing-the-shaders" class="header-anchor">#</a> Writing the shaders</h2> <p>In the same folder as <code>main.rs</code>, create two (2) files: <code>shader.vert</code>, and <code>shader.frag</code>. Write the following code in <code>shader.vert</code>.</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><p>If you've used C/C++ before (or even Java), this syntax should be somewhat familiar. There are some key differences though that i'll go over.</p> <p>First up there's the <code>#version 450</code> line. This specifies the version of GLSL that we're using. I've gone with a later version so we can use many of the advanced GLSL features.</p> <p>We're currently storing vertex data in the shader as <code>positions</code>. This is bad practice as it limits what we can draw with this shader, and it can make the shader super big if we want to use a complex model. Using actual vertex data requires us to use <code>Buffer</code>s, which we'll talk about next time, so we'll turn a blind eye for now.</p> <p>There's also <code>gl_Position</code> and <code>gl_VertexIndex</code> which are built-in variables that define where the vertex position data is going to be stored as 4 floats, and the index of the current vertex in the vertex data.</p> <p>Next up <code>shader.frag</code>.</p> <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>The part that sticks out is the <code>layout(location=0) out vec4 f_color;</code> line. In GLSL you can create <code>in</code> and <code>out</code> variables in your shaders. An <code>in</code> variable will expect data from outside the shader. In the case of the vertex shader, this will come from vertex data. In a fragment shader, an <code>in</code> variable will pull from <code>out</code> variables in the vertex shader. When an <code>out</code> variable is defined in the fragment shader, it means that the value is meant to be written to a buffer to be used outside the shader program.</p> <p><code>in</code> and <code>out</code> variables can also specify a layout. In <code>shader.frag</code> we specify that the <code>out vec4 f_color</code> should be <code>layout(location=0)</code>; this means that the value of <code>f_color</code> will be saved to whatever buffer is at location zero in our application. In most cases, <code>location=0</code> is the current texture from the swapchain aka the screen.</p> <p>You may have noticed that <code>shader.vert</code> doesn't have any <code>in</code> variables nor <code>out</code> variables. <code>gl_Position</code> functions as an out variable for vertex position data, so <code>shader.vert</code> doesn't need any <code>out</code> variables. If we wanted to send more data to fragment shader, we could specify an <code>out</code> variable in <code>shader.vert</code> and an in variable in <code>shader.frag</code>. <em>Note: the location has to match, otherwise the GLSL code will fail to compile</em></p> <div class="language-glsl extra-class"><pre class="language-glsl"><code><span class="token comment">// shader.vert</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> v_color<span class="token punctuation">;</span>
|
|
|
|
<span class="token comment">// shader.frag</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">in</span> <span class="token keyword">vec4</span> v_color<span class="token punctuation">;</span>
|
|
</code></pre></div><h2 id="how-do-we-use-the-shaders"><a href="#how-do-we-use-the-shaders" class="header-anchor">#</a> How do we use the shaders?</h2> <p>This is the part where we finally make the thing in the title: the pipeline. First let's modify <code>State</code> to include the following.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// main.rs</span>
|
|
<span class="token keyword">struct</span> <span class="token type-definition class-name">State</span> <span class="token punctuation">{</span>
|
|
surface<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Surface</span><span class="token punctuation">,</span>
|
|
device<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Device</span><span class="token punctuation">,</span>
|
|
queue<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Queue</span><span class="token punctuation">,</span>
|
|
sc_desc<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">SwapChainDescriptor</span><span class="token punctuation">,</span>
|
|
swap_chain<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">SwapChain</span><span class="token punctuation">,</span>
|
|
size<span class="token punctuation">:</span> <span class="token namespace">winit<span class="token punctuation">::</span>dpi<span class="token punctuation">::</span></span><span class="token class-name">PhysicalSize</span><span class="token operator"><</span><span class="token keyword">u32</span><span class="token operator">></span><span class="token punctuation">,</span>
|
|
<span class="token comment">// NEW!</span>
|
|
render_pipeline<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RenderPipeline</span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span>
|
|
</code></pre></div><p>Now let's move to the <code>new()</code> method, and start making the pipeline. We'll have to load in those shaders we made earlier, as the <code>render_pipeline</code> requires those.</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">"shader.vert"</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">"shader.frag"</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">"shader.vert"</span><span class="token punctuation">,</span> <span class="token string">"main"</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">"shader.frag"</span><span class="token punctuation">,</span> <span class="token string">"main"</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>util<span class="token punctuation">::</span></span><span class="token function">make_spirv</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 keyword">let</span> fs_data <span class="token operator">=</span> <span class="token namespace">wgpu<span class="token punctuation">::</span>util<span class="token punctuation">::</span></span><span class="token function">make_spirv</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 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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ShaderModuleDescriptor</span> <span class="token punctuation">{</span>
|
|
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token string">"Vertex Shader"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
source<span class="token punctuation">:</span> vs_data<span class="token punctuation">,</span>
|
|
flags<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ShaderFlags</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 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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ShaderModuleDescriptor</span> <span class="token punctuation">{</span>
|
|
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token string">"Fragment Shader"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
source<span class="token punctuation">:</span> fs_data<span class="token punctuation">,</span>
|
|
flags<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ShaderFlags</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 punctuation">)</span><span class="token punctuation">;</span>
|
|
</code></pre></div><p>One more thing, we need to create a <code>PipelineLayout</code>. We'll get more into this after we cover <code>Buffer</code>s.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">PipelineLayoutDescriptor</span> <span class="token punctuation">{</span>
|
|
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token string">"Render Pipeline Layout"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
bind_group_layouts<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
|
|
push_constant_ranges<span class="token punctuation">:</span> <span class="token operator">&</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>
|
|
</code></pre></div><p>Finally we have all we need to create the <code>render_pipeline</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RenderPipelineDescriptor</span> <span class="token punctuation">{</span>
|
|
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token string">"Render Pipeline"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
layout<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&</span>render_pipeline_layout<span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
vertex<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">VertexState</span> <span class="token punctuation">{</span>
|
|
module<span class="token punctuation">:</span> <span class="token operator">&</span>vs_module<span class="token punctuation">,</span>
|
|
entry_point<span class="token punctuation">:</span> <span class="token string">"main"</span><span class="token punctuation">,</span> <span class="token comment">// 1.</span>
|
|
buffers<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// 2.</span>
|
|
<span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
fragment<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">FragmentState</span> <span class="token punctuation">{</span> <span class="token comment">// 3.</span>
|
|
module<span class="token punctuation">:</span> <span class="token operator">&</span>fs_module<span class="token punctuation">,</span>
|
|
entry_point<span class="token punctuation">:</span> <span class="token string">"main"</span><span class="token punctuation">,</span>
|
|
targets<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ColorTargetState</span> <span class="token punctuation">{</span> <span class="token comment">// 4.</span>
|
|
format<span class="token punctuation">:</span> sc_desc<span class="token punctuation">.</span>format<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">BlendState</span><span class="token punctuation">::</span><span class="token constant">REPLACE</span><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">BlendState</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><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
<span class="token comment">// continued ...</span>
|
|
</code></pre></div><p>Two things to note here:</p> <ol><li>Here you can specify which function inside of the shader should be called, which is known as the <code>entry_point</code>. I normally use <code>"main"</code> as that's what it would be in OpenGL, but feel free to use whatever name you like. Make sure you specify the same entry point when you're compiling your shaders as you do here where you're exposing them to your pipeline.</li> <li>The <code>buffers</code> field tells <code>wgpu</code> what type of vertices we want to pass to the vertex shader. We're specifying the vertices in the vertex shader itself so we'll leave this empty. We'll put something there in the next tutorial.</li> <li>The <code>fragment_stage</code> is technically optional, so you have to wrap it in <code>Some()</code>. We need it if we want to store color data to the <code>swap_chain</code>.</li> <li>The <code>targets</code> field tells <code>wgpu</code> what color outputs it should set up. Currently we only need one for the <code>swap_chain</code>. We use the <code>swap_chain</code>'s format so that copying to it is easy, and we specify that the blending should just replace old pixel data with new data. We also tell <code>wgpu</code> to write to all colors: red, blue, green, and alpha. <em>We'll talk more about</em><code>color_state</code> <em>when we talk about textures.</em></li></ol> <div class="language-rust extra-class"><pre class="language-rust"><code> primitive<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">PrimitiveState</span> <span class="token punctuation">{</span>
|
|
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> <span class="token comment">// 1.</span>
|
|
strip_index_format<span class="token punctuation">:</span> <span class="token class-name">None</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> <span class="token comment">// 2.</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>
|
|
<span class="token comment">// Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE</span>
|
|
polygon_mode<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">PolygonMode</span><span class="token punctuation">::</span><span class="token class-name">Fill</span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
<span class="token comment">// continued ...</span>
|
|
</code></pre></div><p>The <code>primitive</code> field describes how to interpret our vertices when converting them into triangles.</p> <ol><li>Using <code>PrimitiveTopology::TriangleList</code> means that each three vertices will correspond to one triangle.</li> <li>The <code>front_face</code> and <code>cull_mode</code> fields tell <code>wgpu</code> how to determine whether a given triangle is facing forward or not. <code>FrontFace::Ccw</code> means that a triangle is facing forward if the vertices are arranged in a counter clockwise direction. Triangles that are not considered facing forward are culled (not included in the render) as specified by <code>CullMode::Back</code>. We'll cover culling a bit more when we cover <code>Buffer</code>s.</li></ol> <div class="language-rust extra-class"><pre class="language-rust"><code> depth_stencil<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span> <span class="token comment">// 1.</span>
|
|
multisample<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">MultisampleState</span> <span class="token punctuation">{</span>
|
|
count<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token comment">// 2.</span>
|
|
mask<span class="token punctuation">:</span> <span class="token operator">!</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token comment">// 3.</span>
|
|
alpha_to_coverage_enabled<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 4.</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>The rest of the method is pretty simple:</p> <ol><li>We're not using a depth/stencil buffer currently, so we leave <code>depth_stencil</code> as <code>None</code>. <em>This will change later</em>.</li> <li>This determines how many samples this pipeline will use. Multisampling is a complex topic, so we won't get into it here.</li> <li><code>sample_mask</code> specifies which samples should be active. In this case we are using all of them.</li> <li><code>alpha_to_coverage_enabled</code> has to do with anti-aliasing. We're not covering anti-aliasing here, so we'll leave this as false now.</li></ol> <p>Now all we have to do is save the <code>render_pipeline</code> to <code>State</code> and then we can use it!</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// new()</span>
|
|
<span class="token keyword">Self</span> <span class="token punctuation">{</span>
|
|
surface<span class="token punctuation">,</span>
|
|
device<span class="token punctuation">,</span>
|
|
queue<span class="token punctuation">,</span>
|
|
sc_desc<span class="token punctuation">,</span>
|
|
swap_chain<span class="token punctuation">,</span>
|
|
size<span class="token punctuation">,</span>
|
|
<span class="token comment">// NEW!</span>
|
|
render_pipeline<span class="token punctuation">,</span>
|
|
<span class="token punctuation">}</span>
|
|
</code></pre></div><h2 id="using-a-pipeline"><a href="#using-a-pipeline" class="header-anchor">#</a> Using a pipeline</h2> <p>If you run your program now, it'll take a little longer to start, but it will still show the blue screen we got in the last section. That's because while we created the <code>render_pipeline</code>, we need to modify the code in <code>render()</code> to actually use it.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// render()</span>
|
|
|
|
<span class="token comment">// ...</span>
|
|
<span class="token punctuation">{</span>
|
|
<span class="token comment">// 1.</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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">RenderPassDescriptor</span> <span class="token punctuation">{</span>
|
|
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token string">"Render Pass"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
color_attachments<span class="token punctuation">:</span> <span class="token operator">&</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">&</span>frame<span class="token punctuation">.</span>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>
|
|
ops<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Operations</span> <span class="token punctuation">{</span>
|
|
load<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>
|
|
<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>
|
|
store<span class="token punctuation">:</span> <span class="token boolean">true</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 punctuation">;</span>
|
|
|
|
<span class="token comment">// NEW!</span>
|
|
render_pass<span class="token punctuation">.</span><span class="token function">set_pipeline</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">.</span>render_pipeline<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 2.</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 comment">// 3.</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token comment">// ...</span>
|
|
</code></pre></div><p>We didn't change much, but let's talk about what we did change.</p> <ol><li>We renamed <code>_render_pass</code> to <code>render_pass</code> and made it mutable.</li> <li>We set the pipeline on the <code>render_pass</code> using the one we just created.</li> <li>We tell <code>wgpu</code> to draw <em>something</em> with 3 vertices, and 1 instance. This is where <code>gl_VertexIndex</code> comes from.</li></ol> <p>With all that you should be seeing a lovely brown triangle.</p> <p><img src="data:image/png;base64,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Io8++misWLFi0McDAAA0wDPPPHPxrVljY2O+WR0AAEgzHNHb764HAACYzxw/pxEAAKC/3BEBAADSDUdE/MPf/t6gjwMAAGiI3Rtb3poFAADkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABAOiECAACkEyIAAEA6IQIAAKQTIgAAQDohAgAApBMiAABA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9Ri7of+ECAAAkE6IQB/ZUQOoLmM49JcQgT4xgQFUn7Ec+keIAAAA6YQI9IEdNID6MKZDfwgR6DETFkD9GNuh94QIAACQTohAD9kxA6gvYzz0lhCBHjFBAdSfsR56R4gAAADphAj0gB0ygOYw5kNvCBFYJhMSQPMY+2H5hAgAAJBOiMAy2BEDaC5zACyPEIElMgEBYC6ApRMiAABAOiECS2AHDIBLzAmwNEIEFsmEA8C1zA2weEIEAABIJ0RgEex4AXAj5ghYHCECC2SCAWA+5gpYOCECAACkEyKwAHa4AFgocwYsjBCBeZhQAFgscwfMb3jQBwBl9/14bNCHAABQO+6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmECAAAkE6IAAAA6YQIAACQTogAAADphAgAAJBOiAAAAOmGIyJ2b2wN+jgAAIAG+f/bSmo4C4fjXQAAAABJRU5ErkJggg==" alt="Said lovely brown triangle"></p> <h2 id="compiling-shaders-and-include-spirv"><a href="#compiling-shaders-and-include-spirv" class="header-anchor">#</a> Compiling shaders and include_spirv</h2> <p>Currently we're compiling our shaders when our program starts up, and while this is a valid way of doing things it slows down our programs start up considerably. It also prevents us from using wgpu's <code>include_spirv</code> convenience macro that would inline the spirv code directly. Doing this would also remove our dependency on shaderc (at least for the runtime code).</p> <p>We can do this using a build script. A build script is a file that runs when cargo is compiling your project. We can use it for all sorts of things including compiling our shaders!</p> <p>Add a file called <code>build.rs</code> at the same level as the src directory. It should be at in the same folder as your <code>Cargo.toml</code>.</p> <p>We'll start writing code in it in a bit. First we need to add some things to our <code>Cargo.toml</code>.</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">dependencies</span><span class="token punctuation">]</span>
|
|
<span class="token key property">image</span> <span class="token punctuation">=</span> <span class="token string">"0.23"</span>
|
|
<span class="token key property">winit</span> <span class="token punctuation">=</span> <span class="token string">"0.22"</span>
|
|
<span class="token comment"># shaderc = "0.7" # REMOVED!</span>
|
|
<span class="token key property">cgmath</span> <span class="token punctuation">=</span> <span class="token string">"0.17"</span>
|
|
<span class="token key property">wgpu</span> <span class="token punctuation">=</span> <span class="token string">"0.7"</span>
|
|
<span class="token key property">futures</span> <span class="token punctuation">=</span> <span class="token string">"0.3"</span>
|
|
|
|
<span class="token comment"># NEW!</span>
|
|
<span class="token punctuation">[</span><span class="token table class-name">build-dependencies</span><span class="token punctuation">]</span>
|
|
<span class="token key property">anyhow</span> <span class="token punctuation">=</span> <span class="token string">"1.0"</span>
|
|
<span class="token key property">fs_extra</span> <span class="token punctuation">=</span> <span class="token string">"1.1"</span>
|
|
<span class="token key property">glob</span> <span class="token punctuation">=</span> <span class="token string">"0.3"</span>
|
|
<span class="token key property">shaderc</span> <span class="token punctuation">=</span> <span class="token string">"0.7"</span>
|
|
</code></pre></div><p>We've removed shaderc from our dependencies and added a new <code>[build-depencies]</code> block. These are dependencies for our build script. We know about shaderc, but the other ones are meant to simplify dealing with the file system and dealing with rust errors.</p> <p>Now we can put some code in our <code>build.rs</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
|
|
<span class="token keyword">use</span> <span class="token namespace">glob<span class="token punctuation">::</span></span>glob<span class="token punctuation">;</span>
|
|
<span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>fs<span class="token punctuation">::</span></span><span class="token punctuation">{</span>read_to_string<span class="token punctuation">,</span> write<span class="token punctuation">}</span><span class="token punctuation">;</span>
|
|
<span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>path<span class="token punctuation">::</span></span><span class="token class-name">PathBuf</span><span class="token punctuation">;</span>
|
|
|
|
<span class="token keyword">struct</span> <span class="token type-definition class-name">ShaderData</span> <span class="token punctuation">{</span>
|
|
src<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
|
|
src_path<span class="token punctuation">:</span> <span class="token class-name">PathBuf</span><span class="token punctuation">,</span>
|
|
spv_path<span class="token punctuation">:</span> <span class="token class-name">PathBuf</span><span class="token punctuation">,</span>
|
|
kind<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 punctuation">}</span>
|
|
|
|
<span class="token keyword">impl</span> <span class="token class-name">ShaderData</span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">load</span><span class="token punctuation">(</span>src_path<span class="token punctuation">:</span> <span class="token class-name">PathBuf</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Result</span><span class="token operator"><</span><span class="token keyword">Self</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">let</span> extension <span class="token operator">=</span> src_path
|
|
<span class="token punctuation">.</span><span class="token function">extension</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">context</span><span class="token punctuation">(</span><span class="token string">"File has no extension"</span><span class="token punctuation">)</span><span class="token operator">?</span>
|
|
<span class="token punctuation">.</span><span class="token function">to_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">context</span><span class="token punctuation">(</span><span class="token string">"Extension cannot be converted to &str"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
|
|
<span class="token keyword">let</span> kind <span class="token operator">=</span> <span class="token keyword">match</span> extension <span class="token punctuation">{</span>
|
|
<span class="token string">"vert"</span> <span class="token operator">=></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">"frag"</span> <span class="token operator">=></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">"comp"</span> <span class="token operator">=></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">Compute</span><span class="token punctuation">,</span>
|
|
_ <span class="token operator">=></span> <span class="token macro property">bail!</span><span class="token punctuation">(</span><span class="token string">"Unsupported shader: {}"</span><span class="token punctuation">,</span> src_path<span class="token punctuation">.</span><span class="token function">display</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> src <span class="token operator">=</span> <span class="token function">read_to_string</span><span class="token punctuation">(</span>src_path<span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
|
|
<span class="token keyword">let</span> spv_path <span class="token operator">=</span> src_path<span class="token punctuation">.</span><span class="token function">with_extension</span><span class="token punctuation">(</span><span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"{}.spv"</span><span class="token punctuation">,</span> extension<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
|
|
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token keyword">Self</span> <span class="token punctuation">{</span>
|
|
src<span class="token punctuation">,</span>
|
|
src_path<span class="token punctuation">,</span>
|
|
spv_path<span class="token punctuation">,</span>
|
|
kind<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">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 class-name">Result</span><span class="token operator"><</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">></span> <span class="token punctuation">{</span>
|
|
<span class="token comment">// Collect all shaders recursively within /src/</span>
|
|
<span class="token keyword">let</span> <span class="token keyword">mut</span> shader_paths <span class="token operator">=</span> <span class="token punctuation">[</span>
|
|
<span class="token function">glob</span><span class="token punctuation">(</span><span class="token string">"./src/**/*.vert"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">,</span>
|
|
<span class="token function">glob</span><span class="token punctuation">(</span><span class="token string">"./src/**/*.frag"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">,</span>
|
|
<span class="token function">glob</span><span class="token punctuation">(</span><span class="token string">"./src/**/*.comp"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">,</span>
|
|
<span class="token punctuation">]</span><span class="token punctuation">;</span>
|
|
|
|
<span class="token comment">// This could be parallelized</span>
|
|
<span class="token keyword">let</span> shaders <span class="token operator">=</span> shader_paths
|
|
<span class="token punctuation">.</span><span class="token function">iter_mut</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">flatten</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>glob_result<span class="token closure-punctuation punctuation">|</span></span> <span class="token class-name">ShaderData</span><span class="token punctuation">::</span><span class="token function">load</span><span class="token punctuation">(</span>glob_result<span class="token operator">?</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">::</span><span class="token operator"><</span><span class="token class-name">Vec</span><span class="token operator"><</span><span class="token class-name">Result</span><span class="token operator"><</span>_<span class="token operator">>></span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">into_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">::</span><span class="token operator"><</span><span class="token class-name">Result</span><span class="token operator"><</span><span class="token class-name">Vec</span><span class="token operator"><</span>_<span class="token operator">>></span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">?</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">context</span><span class="token punctuation">(</span><span class="token string">"Unable to create shader compiler"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
|
|
|
|
<span class="token comment">// This can't be parallelized. The [shaderc::Compiler] is not</span>
|
|
<span class="token comment">// thread safe. Also, it creates a lot of resources. You could</span>
|
|
<span class="token comment">// spawn multiple processes to handle this, but it would probably</span>
|
|
<span class="token comment">// be better just to only compile shaders that have been changed</span>
|
|
<span class="token comment">// recently.</span>
|
|
<span class="token keyword">for</span> shader <span class="token keyword">in</span> shaders <span class="token punctuation">{</span>
|
|
<span class="token comment">// This tells cargo to rerun this script if something in /src/ changes.</span>
|
|
<span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"cargo:rerun-if-changed={}"</span><span class="token punctuation">,</span> shader<span class="token punctuation">.</span>src_path<span class="token punctuation">.</span><span class="token function">as_os_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">to_str</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 punctuation">;</span>
|
|
|
|
<span class="token keyword">let</span> compiled <span class="token operator">=</span> compiler<span class="token punctuation">.</span><span class="token function">compile_into_spirv</span><span class="token punctuation">(</span>
|
|
<span class="token operator">&</span>shader<span class="token punctuation">.</span>src<span class="token punctuation">,</span>
|
|
shader<span class="token punctuation">.</span>kind<span class="token punctuation">,</span>
|
|
<span class="token operator">&</span>shader<span class="token punctuation">.</span>src_path<span class="token punctuation">.</span><span class="token function">to_str</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 string">"main"</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 operator">?</span><span class="token punctuation">;</span>
|
|
<span class="token function">write</span><span class="token punctuation">(</span>shader<span class="token punctuation">.</span>spv_path<span class="token punctuation">,</span> compiled<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 operator">?</span><span class="token punctuation">;</span>
|
|
<span class="token punctuation">}</span>
|
|
|
|
<span class="token class-name">Ok</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 that in place we can replace our shader compiling code in <code>main.rs</code> with just two lines!</p> <div class="language-rust extra-class"><pre class="language-rust"><code><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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token macro property">include_spirv!</span><span class="token punctuation">(</span><span class="token string">"shader.vert.spv"</span><span class="token punctuation">)</span><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">&</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token macro property">include_spirv!</span><span class="token punctuation">(</span><span class="token string">"shader.frag.spv"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
</code></pre></div><div class="note"><p>I'm glossing over the code in the build script as this guide is focused on wgpu related topics. Designing build scripts is a topic in and of itself, and going into it in detail would be quite a long tangent. You can learn more about build scripts in <a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html" target="_blank" rel="noopener noreferrer">The Cargo Book<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> <h2 id="challenge"><a href="#challenge" class="header-anchor">#</a> Challenge</h2> <p>Create a second pipeline that uses the triangle's position data to create a color that it then sends to the fragment shader to use for <code>f_color</code>. Have the app swap between these when you press the spacebar. <em>Hint: use</em> <code>in</code> <em>and</em> <code>out</code> <em>variables in a separate shader.</em></p> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial3-pipeline/" 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">2/19/2021, 3:56:47 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
|
|
←
|
|
<a href="/learn-wgpu/beginner/tutorial2-swapchain/" class="prev">
|
|
The Swapchain
|
|
</a></span> <span class="next"><a href="/learn-wgpu/beginner/tutorial4-buffer/">
|
|
Buffers and Indices
|
|
</a>
|
|
→
|
|
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
|
|
<script src="/learn-wgpu/assets/js/app.6593075e.js" defer></script><script src="/learn-wgpu/assets/js/2.da3fd46f.js" defer></script><script src="/learn-wgpu/assets/js/12.26aabcb1.js" defer></script><script src="/learn-wgpu/assets/js/22.2132e362.js" defer></script>
|
|
</body>
|
|
</html>
|