Skip to content

Commit 2109eb5

Browse files
committed
Add further explanation of views. Improve Image Views chapter
1 parent 298a423 commit 2109eb5

File tree

1 file changed

+59
-50
lines changed

1 file changed

+59
-50
lines changed

en/03_Drawing_a_triangle/01_Presentation/02_Image_views.adoc

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22

33
= Image views
44

5-
To use any `VkImage`, including those in the swap chain, in the render pipeline
6-
we have to create a `VkImageView` object. An image view is quite literally a
7-
view into an image. It describes how to access the image and which part of the
8-
image to access, for example, if it should be treated as a 2D texture depth
9-
texture without any mipmapping levels.
5+
In Vulkan, accessing and manipulating resources isn't done directly but rather
6+
through *views* - these describe how to look at (or *view*) a subset of the
7+
underlying data in a desired way. For instance, `VkBuffer` refers to a buffer
8+
object which represents a linear array of data. To use a `VkBuffer` you have to
9+
create a `VkBufferView` object which describes, among other things, the
10+
accessible contiguous range of the underlying data (this is done by providing
11+
an `offset` and a `range`).
12+
13+
Similarly, to use any `VkImage`, including those in the swap chain, in the
14+
render pipeline we have to create a `VkImageView` object. The `VkImageView`
15+
describes how to interpret the underlying image and which part of it to access,
16+
for example, if it should be treated as a 2D texture depth texture without any
17+
mipmapping levels.
1018

1119
In this chapter we'll write a `createImageViews` function that creates a basic
1220
image view for every image in the swap chain so that we can use them as color
@@ -20,7 +28,7 @@ std::vector<vk::raii::ImageView> swapChainImageViews;
2028
----
2129

2230
Create the `createImageViews` function and call it right after swap chain
23-
creation.
31+
creation:
2432

2533
[,c++]
2634
----
@@ -40,61 +48,61 @@ void createImageViews() {
4048
----
4149

4250
The parameters for image view creation are specified in a
43-
`VkImageViewCreateInfo` structure. The first few parameters are the flags,
44-
this isn't needed in our case, we'll add the images in the upcoming for loop.
45-
Next, we specify that we're rendering to a 2d screen. If we were wanting
46-
to render to a 3d screen or cube map, those are also options as is a 1d
47-
screen. As you can probably guess, we'd want a 2d render target in most
51+
`VkImageViewCreateInfo` structure. The first field is `flags` which is not
52+
needed in our case.
53+
54+
Next is the `image` field which will be set to each `VkImage` from the swap
55+
chain in the upcoming loop over the swap chain images.
56+
57+
Next, in the `viewType` field, we specify that we're rendering to a 2D screen.
58+
If we wanted to render to a 3D screen or cube map, those are also options as is
59+
a 1D screen. As you can probably guess, we'd want a 2D render target in most
4860
cases when we're rendering to a screen.
4961

50-
Next, we specify the image format; this is how the colorspace
51-
components are configured so you get the right color format in your
52-
renders. Next, components aren't needed for our swap chain; we'll talk
53-
about them in a bit though. The last variable is the SubResource range,
54-
which is necessary, and we'll talk about shortly.
62+
Next, in the `format` field, we specify the image format; this is how the
63+
colorspace components are configured so you get the right color format in your
64+
renders. In the case of swap chain image views, we want to use the same format
65+
as the underlying swap chain `VkImage` objects.
66+
67+
The last field is the `subresourceRange` which describes what the purpose of
68+
the image is and which part of it should be accessed. Our images will be used as
69+
color targets without any mipmapping levels or multiple layers.
70+
71+
The `createImageViews` function should now look something like this:
5572

5673
[,c++]
5774
----
5875
void createImageViews() {
5976
swapChainImageViews.clear();
6077
61-
vk::ImageViewCreateInfo imageViewCreateInfo{ .viewType = vk::ImageViewType::e2D, .format = swapChainImageFormat,
62-
.subresourceRange = { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } };
78+
vk::ImageViewCreateInfo imageViewCreateInfo{
79+
/* .image = will be overwritten in the subsequent loop */
80+
.viewType = vk::ImageViewType::e2D,
81+
.format = swapChainImageFormat,
82+
.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eColor,
83+
.baseMipLevel = 0,
84+
.levelCount = 1,
85+
.baseArrayLayer = 0,
86+
.layerCount = 1},
87+
};
6388
}
6489
----
6590

66-
The `components` field allows you to swizzle the color channels around. For
67-
example, you can map all the channels to the red channel for a monochrome
68-
texture. You can also map constant values of `0` and `1` to a channel. In our
69-
case, we'll stick to the default mapping by accepting the constructed
70-
defaults, but here's how to explicitly do it:
71-
72-
[,c++]
73-
----
74-
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
75-
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
76-
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
77-
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
78-
----
79-
80-
The `subresourceRange` field describes what the image's purpose is and which
81-
part of the image should be accessed. Our images will be used as color targets
82-
without any mipmapping levels or multiple layers.
83-
84-
[,c++]
85-
----
86-
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
87-
createInfo.subresourceRange.baseMipLevel = 0;
88-
createInfo.subresourceRange.levelCount = 1;
89-
createInfo.subresourceRange.baseArrayLayer = 0;
90-
createInfo.subresourceRange.layerCount = 1;
91-
----
92-
93-
An easy way to specify all of that is this single line:
91+
The `components` field (which is kept to default here) allows you to swizzle
92+
the color channels around. For example, you can map all the channels to the red
93+
channel for a monochrome texture. You can also map constant values of `0` and
94+
`1` to a channel. The concept of swizzling will become much clearer once we get
95+
to the Shader Modules chapter. In our case, we'll stick to the default mapping
96+
by accepting the constructed defaults, but here's how to explicitly do it:
9497

9598
[,c++]
9699
----
97-
vk::ImageViewCreateInfo imageViewCreateInfo( {}, {}, vk::ImageViewType::e2D, swapChainImageFormat, {}, { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } );
100+
imageViewCreateInfo.components = {
101+
.r = vk::ComponentSwizzle::eIdentity,
102+
.g = vk::ComponentSwizzle::eIdentity,
103+
.b = vk::ComponentSwizzle::eIdentity,
104+
.a = vk::ComponentSwizzle::eIdentity,
105+
};
98106
----
99107

100108
If you were working on a stereographic 3D application, then you would create a
@@ -112,7 +120,7 @@ tutorial, but even those use cases can be rendered to with these same
112120
structures and techniques we describe here.
113121

114122
Next, set up the loop that iterates over all the swap chain images and add
115-
them to our structure.
123+
them to our structure:
116124

117125
[,c++]
118126
----
@@ -131,8 +139,9 @@ for (auto image : swapChainImages) {
131139
}
132140
----
133141

134-
An image view is sufficient to start using an image as a texture, but it's not quite ready to be used as a render target just yet.
135-
That requires one more step, known as a framebuffer.
142+
An image view is sufficient to start using an image as a texture, but it's not
143+
quite ready to be used as a render target just yet. That requires one more step,
144+
known as a *framebuffer*.
136145
In the xref:/03_Drawing_a_triangle/02_Graphics_pipeline_basics/00_Introduction.adoc[next chapters,] we'll have to set up the graphics pipeline.
137146

138147
link:/attachments/07_image_views.cpp[C{pp} code]

0 commit comments

Comments
 (0)