2 |
Donate
3 |
4 |
5 | Austin Johnson (active maintainer)
6 | Become a Patron!
7 |
8 |
9 |
10 | Rukai (current maintainer)
11 | Become a Patron!
12 |
13 |
14 |
15 | Tomaka (original developer)
16 | Become a Patron!
17 |
18 |
19 |
Thank you very much!
20 |
21 |
Thank you to all of tomaka's current Patreon donators:
22 |
23 |
24 | - Stephan Buys
25 | - Sanghyeon Seo
26 | - Steven McGuire
27 | - Iban Eguia
28 | - Alex Whitney
29 | - Lucas Kent
30 | - Daniel Collin
31 | - Michael Carpenter
32 | - Kyle Gretchev
33 | - Josh Leverette
34 | - Martin Pärtel
35 | - David Harvey-Macaulay
36 | - Benjamin Wasty
37 | - Alain Galvan
38 | - Coleman McFarland
39 | - Tobias Schönberg
40 | - Elias Haviola
41 | - Neil Henning
42 | - patapon
43 | - Josiah Gaskin
44 | - Jorge Aparicio
45 | - Tim Neumann
46 | - Felix Schütt
47 | - David Muchene
48 | - Joni Katajamäki
49 | - Dustin Bensing
50 | - Jacob Kiesel
51 | - Corentin Henry
52 | - Edward Pierzchalski
53 | - Mitchell Nordine
54 | - Zack Peterson
55 | - Zane
56 | - Tim Ryan
57 | - Jon Ringer
58 | - Dan Watkins
59 | - camille viot
60 | - Tinco Andringa
61 | - Tim Hutt
62 | - Oliver Uvman
63 | - Karl Hobley
64 | - Dennis Möhlmann
65 | - Robert Long
66 | - Michael Sierks
67 | - Ty Overby
68 | - Praveen
69 | - ozkriff
70 | - Nick Linker
71 | - htee
72 | - vladimir s
73 | - Mark Stacey
74 | - John Salamon
75 | - Claudio Capobianco
76 | - Wouter van der Stoel
77 | - Arne Brix
78 | - Olivier Saut
79 | - Jakub "Limeth" Hlusička
80 | - Pyry Kontio
81 | - Lucien Greathouse
82 | - Jeff Muizelaar
83 | - Pascal
84 | - Simon N Heath
85 | - Tom Edge
86 | - Sebastián Ramírez Magrí
87 | - Lưu Hoàng
88 | - nanoplink
89 | - Andreas Fischer
90 | - Drew Fisher
91 | - Grant Miner
92 | - Wim Vander Schelden
93 | - Matt Brubeck
94 | - trgk
95 | - Jordan Miner
96 | - Erika
97 | - Kametrixom Tikara
98 | - Victor Brekenfeld
99 | - Ayose
100 | - Jesper
101 | - Mitchell Bruckner
102 | - Joe ST
103 | - Mikael
104 | - Christopher Armstrong
105 |
106 |
107 |
Thank you to all of Austin Johnson's current Patreon donators (as of May 15th 2020):
108 |
109 |
110 | - Jeff Wright
111 | - Cameron Garnham
112 | - is8ac
113 |
114 |
115 |
--------------------------------------------------------------------------------
/static/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | * General
3 | */
4 | @import url('https://fonts.googleapis.com/css?family=Muli');
5 |
6 | body {
7 | background-color: #222;
8 | color: white;
9 | font-family: 'Muli', Verdana, Geneva, Tahoma, sans-serif;
10 | font-size: 1.1rem;
11 | margin: 0;
12 | padding: 0;
13 | }
14 |
15 | @media (max-width: 1200px) {
16 | body {
17 | font-size: 10px;
18 | }
19 | }
20 |
21 | a {
22 | color: white;
23 | }
24 |
25 | pre {
26 | border: 1px dashed #888;
27 | border-radius: 2px;
28 | }
29 |
30 | /*
31 | * Header
32 | */
33 | header {
34 | background-color: #2e3d9d;
35 | background-image: url(/logo.png);
36 | background-repeat: no-repeat, repeat;
37 | background-size: auto 80%, cover;
38 | background-position: 5% 70%;
39 | display: block;
40 | margin: 0;
41 | padding: 0;
42 | }
43 |
44 | header h1 {
45 | font-size: 3rem;
46 | margin: 0;
47 | padding: 1rem 0 0.4rem;
48 | text-align: center;
49 | }
50 |
51 | header h2 {
52 | font-size: 1.4rem;
53 | margin: 0;
54 | margin-bottom: 1rem;
55 | padding: 0;
56 | text-align: center;
57 | }
58 |
59 | header ul {
60 | display: block;
61 | margin: 0;
62 | padding: 0.9rem 0;
63 | text-align: center;
64 | }
65 |
66 | header ul li {
67 | display: inline;
68 | margin: 0;
69 | padding: 0;
70 | font-weight: bold;
71 | text-transform: lowercase;
72 | }
73 |
74 | header ul li:first-child::before {
75 | content: "";
76 | }
77 |
78 | header ul li::before {
79 | content: " - ";
80 | }
81 |
82 | header ul li a {
83 | text-decoration: none;
84 | }
85 |
86 | header ul li a:hover {
87 | text-decoration: underline;
88 | }
89 |
90 | /*
91 | * Home page
92 | */
93 | #home {
94 | padding: 2rem 0;
95 | }
96 |
97 | #home #infos {
98 | display: flex;
99 | align-items: stretch;
100 | flex-direction: row;
101 | flex-wrap: wrap;
102 | text-align: center;
103 | margin: 0 auto;
104 | padding: 3rem 0 5rem;
105 | }
106 |
107 | @media (min-width: 1200px) {
108 | #home #infos {
109 | width: 80%;
110 | }
111 | }
112 |
113 | #home #infos > li {
114 | display: block;
115 | flex-grow: 1;
116 | flex-basis: 10rem;
117 | padding: 2rem 2rem;
118 | }
119 |
120 | #home #infos > li + li {
121 | border-left: 1px dashed rgba(255, 255, 255, 0.5);
122 | }
123 |
124 | #home #jump {
125 | text-align: center;
126 | }
127 |
128 | #home #jump a {
129 | background-color: #2e3d9d;
130 | border: 10px solid rgba(0, 0, 0, 0.5);
131 | border-radius: 20px;
132 | display: inline-block;
133 | margin: 0 1rem 1rem;
134 | padding: 1rem 2rem;
135 | text-decoration: none;
136 | }
137 |
138 | #home #jump a:hover {
139 | background-color: #2e3d9d;
140 | }
141 |
142 | #home #jump a:active {
143 | border-color: black;
144 | }
145 |
146 | /*
147 | * Donate page
148 | */
149 | #donate {
150 | margin: 0 10%;
151 | }
152 |
153 | /*
154 | * Guides
155 | */
156 | #guides {
157 | display: flex;
158 | flex-direction: row;
159 | align-items: stretch;
160 | }
161 |
162 | #guides > nav {
163 | background-color: #444;
164 | font-size: 0.95rem;
165 | padding: 1rem 5rem 1rem 3rem;
166 | flex-basis: 10vw;
167 | flex-grow: 0.05;
168 | }
169 |
170 | #guides > nav a {
171 | text-decoration: none;
172 | }
173 |
174 | #guides > nav a:hover {
175 | color: #ddd;
176 | text-decoration: underline;
177 | }
178 |
179 | #guides > nav h2:first-child {
180 | margin-top: 0.5rem;
181 | }
182 |
183 | #guides > nav ul {
184 | list-style-type: none;
185 | margin: 1.7rem 0 0;
186 | padding: 0;
187 | }
188 |
189 | #guides > nav ul li {
190 | border-left: 2px solid rgba(255, 255, 255, 0.1);
191 | margin: 0;
192 | padding: 0.1rem 0;
193 | padding-left: 1.7rem;
194 | text-indent: -1.0rem;
195 | }
196 |
197 | #guides > nav ul li.current-page a {
198 | color: #6c7af3;
199 | font-weight: bold;
200 | }
201 |
202 | #guides > div {
203 | flex: 1;
204 | font-family: sans-serif;
205 | font-size: 0.9rem;
206 | padding: 1rem 2rem;
207 | }
208 |
--------------------------------------------------------------------------------
/content/guide/compute_pipeline/compute_intro.md:
--------------------------------------------------------------------------------
1 | # Introduction to compute operations
2 |
3 | Before we go further, we need to understand the difference between a CPU and a GPU. As a reminder,
4 | the CPU is what executes your Rust program, while the GPU is what we are trying to interface with.
5 |
6 | Both the CPU and the GPU execute instructions one by one. The instructions available for regular
7 | programs that run on the CPU include, for example, modifying a value in memory, or performing some
8 | mathematical operation.
9 |
10 | The instructions that a GPU can execute are often limited, but they can operate on a lot of
11 | data at once. You can, for example, instruct the GPU to multiply thirty-two values by a constant,
12 | in approximately the same time that a CPU would take to multiply a single value by that constant
13 | (ignoring the overhead of transferring data between the two devices).
14 |
15 | This is what makes GPUs very good at parallel computations which require executing the same
16 | sequence of operation on multiple values. While a CPU would perform this sequence on each value one
17 | by one, a GPU can perform it on multiple values at once.
18 |
19 | > **Note**: See also [SIMD](https://en.wikipedia.org/wiki/SIMD).
20 |
21 | > **Note**: In [a previous section](/guide/device-creation) we talked about *queues*. These queues
22 | > are usually foremost *software* queues, and not actual hardware constructs.
23 |
24 | > **Note**: You can find the [full source code of this chapter
25 | > here](https://github.com/vulkano-rs/vulkano-www/blob/master/chapter_code/src/bin/compute_pipeline.rs).
26 |
27 | ## Usability
28 |
29 | Vulkan (or any other API) doesn't let you directly control the threading aspect of the GPU.
30 | In order to perform an operation with multiple values at once, you will only need to indicate the
31 | list of operations to perform on **one** value. The Vulkan implementation will automatically make
32 | the necessary adjustments to make your operation run on multiple values at once.
33 |
34 | This makes using a GPU much easier than if you had to manually control everything. However, you
35 | still need to be aware that your program will run multiple times in parallel, because it has
36 | consequences on what you can do without causing data races.
37 |
38 | ## Example in this guide
39 |
40 | For the purpose of this guide, we are going to do something very simple: we are going to multiply
41 | 65536 values by the constant 12. Even though this doesn't serve any purpose, it is a good starting
42 | point example. Most real-world usages of the GPU involve complex mathematical algorithms, and thus
43 | are not really appropriate for a tutorial.
44 |
45 | As explained above, you don't need to use any `for` loop or anything similar of that sort. All we
46 | have to do is write the operation that is performed on *one* value, and ask the GPU to execute
47 | it 65536 times. Our operation here is therefore simply (in pseudo-code):
48 |
49 | ```glsl
50 | // `index` will range from 0 to 65536
51 | buffer_content[index] *= 12;
52 | ```
53 |
54 | While it may look like this code multiplies a single value by 12, in reality the Vulkan
55 | implementation will automatically handle all the details that make it possible to run this in
56 | parallel multiple times in the most optimized way.
57 |
58 | As a preliminary action we are going to create the buffer that will contain the values. This is
59 | similar to what we already did twice:
60 |
61 | ```rust
62 | let data_iter = 0..65536u32;
63 | let data_buffer = Buffer::from_iter(
64 | &memory_allocator,
65 | BufferCreateInfo {
66 | usage: BufferUsage::STORAGE_BUFFER,
67 | ..Default::default()
68 | },
69 | AllocationCreateInfo {
70 | usage: MemoryUsage::Upload,
71 | ..Default::default()
72 | },
73 | data_iter,
74 | )
75 | .expect("failed to create buffer");
76 | ```
77 |
78 | The `data_buffer` buffer now contains the data before the transformation, and we are going to
79 | perform the calculation on each element.
80 | Although notice that we're using `STORAGE_BUFFER` usage this time, since the buffer will be used
81 | in the compute shader.
82 |
83 | [The next section of the guide](/guide/compute-pipeline) will indicate how to actually code this
84 | operation.
85 |
--------------------------------------------------------------------------------
/content/guide/windowing/introduction.md:
--------------------------------------------------------------------------------
1 | # Windowing introduction
2 |
3 | Up until now, we have only created applications that perform one quick action and then exit. What
4 | we are going to do next is create a window in order to draw graphics on it, and keep our
5 | application running forever until the window is closed.
6 |
7 | Strictly speaking, creating a window and handling events is **not** covered by vulkano. Vulkano,
8 | however, is capable of rendering to window(s).
9 |
10 | > **Note**: You can find the [full source code of this chapter
11 | > here](https://github.com/vulkano-rs/vulkano-www/blob/master/chapter_code/src/bin/windowing.rs).
12 |
13 | ## Creating a window
14 |
15 | In order to create a window, we will use the `winit` crate. And while we're at it, we are also
16 | going to add a dependency to the `vulkano-win` crate which is a link between vulkano and winit.
17 |
18 | Add to your `Cargo.toml` dependencies:
19 |
20 | ```toml
21 | vulkano-win = "0.33.0"
22 | winit = "0.28.3"
23 | ```
24 |
25 | We encourage you to browse [the documentation of `winit`](https://docs.rs/winit).
26 |
27 | Because the objects that come with creating a window are not part of Vulkan itself, the first thing
28 | that you will need to do is to enable all non-core extensions required to draw a window.
29 | `vulkano_win` automatically provides them for us, so the only thing left is to pass them on to the
30 | instance creation:
31 |
32 | ```rust
33 | use vulkano::instance::{Instance, InstanceCreateInfo};
34 |
35 | let library = VulkanLibrary::new().expect("no local Vulkan library/DLL");
36 | let required_extensions = vulkano_win::required_extensions(&library);
37 | let instance = Instance::new(
38 | library,
39 | InstanceCreateInfo {
40 | enabled_extensions: required_extensions,
41 | ..Default::default()
42 | },
43 | )
44 | .expect("failed to create instance");
45 | ```
46 |
47 | Now, let's create the actual window:
48 |
49 | ```rust
50 | use vulkano_win::VkSurfaceBuild;
51 | use winit::event_loop::{EventLoop};
52 | use winit::window::{WindowBuilder};
53 |
54 | let event_loop = EventLoop::new(); // ignore this for now
55 | let surface = WindowBuilder::new()
56 | .build_vk_surface(&event_loop, instance.clone())
57 | .unwrap();
58 | ```
59 |
60 | As you can see, we created a new object, called *surface*.
61 |
62 | The *surface* is a cross-platform abstraction over the actual window object, that vulkano can use
63 | for rendering. As for the window itself, it can be retrieved by calling `surface.window()`, which
64 | you can use to manipulate and change its default properties.
65 |
66 | After you made the change, running the program should now open a window, then immediately
67 | close it when the `main` function exits.
68 |
69 | ## Events handling
70 |
71 | In order to make our application run for as long as the window is alive, we need to handle the
72 | window's events. This is typically done after initialization, and right before the end of the
73 | `main` function. Using the `event_loop` object:
74 |
75 | ```rust
76 | use winit::event::{Event, WindowEvent};
77 | use winit::event_loop::ControlFlow;
78 |
79 | event_loop.run(|event, _, control_flow| {
80 | match event {
81 | Event::WindowEvent {
82 | event: WindowEvent::CloseRequested,
83 | ..
84 | } => {
85 | *control_flow = ControlFlow::Exit;
86 | },
87 | _ => ()
88 | }
89 | });
90 | ```
91 |
92 | What this code does is block the main thread forever, and calls the closure whenever the events
93 | loop (which we used to create our window) receives an event. These events include the events that
94 | are tied to our window, such as mouse movements.
95 |
96 | When the user wants to close the window, a `WindowEvent::CloseRequested` event is received, which
97 | makes our closure set the `control_flow` to `ControlFlow::Exit` which signals to winit that we want
98 | an exit.
99 |
100 |
101 |
104 |
105 | Right now, all we're doing is creating a window and keeping our program alive for as long as the
106 | window isn't closed. The next section will show how to initialize what is called a *swapchain* on
107 | the window's surface.
108 |
109 | Next: [Swapchain creation](/guide/windowing/swapchain-creation)
110 |
--------------------------------------------------------------------------------
/content/guide/images/image_creation.md:
--------------------------------------------------------------------------------
1 | # Creating an image
2 |
3 | In [the buffers creation section of the guide](/guide/buffer-creation) we saw that in order for
4 | the GPU to access data we had to put it in a *buffer*.
5 | This is not exactly true, as there is an alternative which are ***images***.
6 |
7 | An *image* in the context of Vulkan designates a multidimensional array of pixels.
8 | There are various hardcoded formats that the pixels of an image can use.
9 |
10 |