@@ -81,3 +81,101 @@ auto vma::create_image(ImageCreateInfo const& create_info,
81
81
};
82
82
}
83
83
```
84
+
85
+ For creating sampled images, we need both the image bytes and size (extent). Wrap that into a struct:
86
+
87
+ ``` cpp
88
+ struct Bitmap {
89
+ std::span<std::byte const> bytes{};
90
+ glm::ivec2 size{};
91
+ };
92
+ ```
93
+
94
+ The creation process is similar to device buffers: requiring a staging copy, but it also needs layout transitions. In short:
95
+
96
+ 1. Create the image and staging buffer
97
+ 1. Transition the layout from Undefined to TransferDst
98
+ 1. Record a buffer image copy operation
99
+ 1. Transition the layout from TransferDst to ShaderReadOnlyOptimal
100
+
101
+ ```cpp
102
+ auto vma::create_sampled_image(ImageCreateInfo const& create_info,
103
+ CommandBlock command_block, Bitmap const& bitmap)
104
+ -> Image {
105
+ // create image.
106
+ // no mip-mapping right now: 1 level.
107
+ auto const mip_levels = 1u;
108
+ auto const usize = glm::uvec2{bitmap.size};
109
+ auto const extent = vk::Extent2D{usize.x, usize.y};
110
+ auto const usage =
111
+ vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled;
112
+ auto ret = create_image(create_info, usage, mip_levels,
113
+ vk::Format::eR8G8B8A8Srgb, extent);
114
+
115
+ // create staging buffer.
116
+ auto const buffer_ci = BufferCreateInfo{
117
+ .allocator = create_info.allocator,
118
+ .usage = vk::BufferUsageFlagBits::eTransferSrc,
119
+ .queue_family = create_info.queue_family,
120
+ };
121
+ auto const staging_buffer = create_buffer(buffer_ci, BufferMemoryType::Host,
122
+ bitmap.bytes.size_bytes());
123
+
124
+ // can't do anything if either creation failed.
125
+ if (!ret.get().image || !staging_buffer.get().buffer) { return {}; }
126
+
127
+ // copy bytes into staging buffer.
128
+ std::memcpy(staging_buffer.get().mapped, bitmap.bytes.data(),
129
+ bitmap.bytes.size_bytes());
130
+
131
+ // transition image for transfer.
132
+ auto dependency_info = vk::DependencyInfo{};
133
+ auto subresource_range = vk::ImageSubresourceRange{};
134
+ subresource_range.setAspectMask(vk::ImageAspectFlagBits::eColor)
135
+ .setLayerCount(1)
136
+ .setLevelCount(mip_levels);
137
+ auto barrier = vk::ImageMemoryBarrier2{};
138
+ barrier.setImage(ret.get().image)
139
+ .setSrcQueueFamilyIndex(create_info.queue_family)
140
+ .setDstQueueFamilyIndex(create_info.queue_family)
141
+ .setOldLayout(vk::ImageLayout::eUndefined)
142
+ .setNewLayout(vk::ImageLayout::eTransferDstOptimal)
143
+ .setSubresourceRange(subresource_range)
144
+ .setSrcStageMask(vk::PipelineStageFlagBits2::eTopOfPipe)
145
+ .setSrcAccessMask(vk::AccessFlagBits2::eNone)
146
+ .setDstStageMask(vk::PipelineStageFlagBits2::eTransfer)
147
+ .setDstAccessMask(vk::AccessFlagBits2::eMemoryRead |
148
+ vk::AccessFlagBits2::eMemoryWrite);
149
+ dependency_info.setImageMemoryBarriers(barrier);
150
+ command_block.command_buffer().pipelineBarrier2(dependency_info);
151
+
152
+ auto buffer_image_copy = vk::BufferImageCopy2{};
153
+ auto subresource_layers = vk::ImageSubresourceLayers{};
154
+ subresource_layers.setAspectMask(vk::ImageAspectFlagBits::eColor)
155
+ .setLayerCount(1)
156
+ .setLayerCount(mip_levels);
157
+ buffer_image_copy.setImageSubresource(subresource_layers)
158
+ .setImageExtent(vk::Extent3D{extent.width, extent.height, 1});
159
+ auto copy_info = vk::CopyBufferToImageInfo2{};
160
+ copy_info.setDstImage(ret.get().image)
161
+ .setDstImageLayout(vk::ImageLayout::eTransferDstOptimal)
162
+ .setSrcBuffer(staging_buffer.get().buffer)
163
+ .setRegions(buffer_image_copy);
164
+ command_block.command_buffer().copyBufferToImage2(copy_info);
165
+
166
+ // transition image for sampling.
167
+ barrier.setOldLayout(barrier.newLayout)
168
+ .setNewLayout(vk::ImageLayout::eShaderReadOnlyOptimal)
169
+ .setSrcStageMask(barrier.dstStageMask)
170
+ .setSrcAccessMask(barrier.dstAccessMask)
171
+ .setDstStageMask(vk::PipelineStageFlagBits2::eAllGraphics)
172
+ .setDstAccessMask(vk::AccessFlagBits2::eMemoryRead |
173
+ vk::AccessFlagBits2::eMemoryWrite);
174
+ dependency_info.setImageMemoryBarriers(barrier);
175
+ command_block.command_buffer().pipelineBarrier2(dependency_info);
176
+
177
+ command_block.submit_and_wait();
178
+
179
+ return ret;
180
+ }
181
+ ```
0 commit comments