@@ -81,3 +81,101 @@ auto vma::create_image(ImageCreateInfo const& create_info,
8181 };
8282}
8383```
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