| Flutter Impeller |

blit_command_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/backend/vulkan/blit_command_vk.h"
6
7 #include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
8 #include "impeller/renderer/backend/vulkan/texture_vk.h"
9
10 namespace impeller {
11
12 BlitEncodeVK::~BlitEncodeVK() = default;
13
14 //------------------------------------------------------------------------------
15 /// BlitCopyTextureToTextureCommandVK
16 ///
17
18 BlitCopyTextureToTextureCommandVK::~BlitCopyTextureToTextureCommandVK() =
19 default;
20
21 std::string BlitCopyTextureToTextureCommandVK::GetLabel() const {
22 return label;
23 }
24
25 bool BlitCopyTextureToTextureCommandVK::Encode(
26 CommandEncoderVK& encoder) const {
27 const auto& cmd_buffer = encoder.GetCommandBuffer();
28
29 const auto& src = TextureVK::Cast(*source);
30 const auto& dst = TextureVK::Cast(*destination);
31
32 if (!encoder.Track(source) || !encoder.Track(destination)) {
33 return false;
34 }
35
36 BarrierVK src_barrier;
37 src_barrier.cmd_buffer = cmd_buffer;
38 src_barrier.new_layout = vk::ImageLayout::eTransferSrcOptimal;
39 src_barrier.src_access = vk::AccessFlagBits::eTransferWrite |
40 vk::AccessFlagBits::eShaderWrite |
41 vk::AccessFlagBits::eColorAttachmentWrite;
42 src_barrier.src_stage = vk::PipelineStageFlagBits::eTransfer |
43 vk::PipelineStageFlagBits::eFragmentShader |
44 vk::PipelineStageFlagBits::eColorAttachmentOutput;
45 src_barrier.dst_access = vk::AccessFlagBits::eTransferRead;
46 src_barrier.dst_stage = vk::PipelineStageFlagBits::eTransfer;
47
48 BarrierVK dst_barrier;
49 dst_barrier.cmd_buffer = cmd_buffer;
50 dst_barrier.new_layout = vk::ImageLayout::eTransferDstOptimal;
51 dst_barrier.src_access = {};
52 dst_barrier.src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
53 dst_barrier.dst_access =
54 vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferWrite;
55 dst_barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader |
56 vk::PipelineStageFlagBits::eTransfer;
57
58 if (!src.SetLayout(src_barrier) || !dst.SetLayout(dst_barrier)) {
59 VALIDATION_LOG << "Could not complete layout transitions.";
60 return false;
61 }
62
63 vk::ImageCopy image_copy;
64
65 image_copy.setSrcSubresource(
66 vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
67 image_copy.setDstSubresource(
68 vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
69
70 image_copy.srcOffset =
71 vk::Offset3D(source_region.origin.x, source_region.origin.y, 0);
72 image_copy.dstOffset =
73 vk::Offset3D(destination_origin.x, destination_origin.y, 0);
74 image_copy.extent =
75 vk::Extent3D(source_region.size.width, source_region.size.height, 1);
76
77 // Issue the copy command now that the images are already in the right
78 // layouts.
79 cmd_buffer.copyImage(src.GetImage(), //
80 src_barrier.new_layout, //
81 dst.GetImage(), //
82 dst_barrier.new_layout, //
83 image_copy //
84 );
85
86 return true;
87 }
88
89 //------------------------------------------------------------------------------
90 /// BlitCopyTextureToBufferCommandVK
91 ///
92
93 BlitCopyTextureToBufferCommandVK::~BlitCopyTextureToBufferCommandVK() = default;
94
95 std::string BlitCopyTextureToBufferCommandVK::GetLabel() const {
96 return label;
97 }
98
99 bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const {
100 const auto& cmd_buffer = encoder.GetCommandBuffer();
101
102 // cast source and destination to TextureVK
103 const auto& src = TextureVK::Cast(*source);
104
105 if (!encoder.Track(source) || !encoder.Track(destination)) {
106 return false;
107 }
108
109 BarrierVK barrier;
110 barrier.cmd_buffer = cmd_buffer;
111 barrier.new_layout = vk::ImageLayout::eTransferSrcOptimal;
112 barrier.src_access = vk::AccessFlagBits::eShaderWrite |
113 vk::AccessFlagBits::eTransferWrite |
114 vk::AccessFlagBits::eColorAttachmentWrite;
115 barrier.src_stage = vk::PipelineStageFlagBits::eFragmentShader |
116 vk::PipelineStageFlagBits::eTransfer |
117 vk::PipelineStageFlagBits::eColorAttachmentOutput;
118 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
119 barrier.dst_stage = vk::PipelineStageFlagBits::eVertexShader |
120 vk::PipelineStageFlagBits::eFragmentShader;
121
122 const auto& dst = DeviceBufferVK::Cast(*destination);
123
124 vk::BufferImageCopy image_copy;
125 image_copy.setBufferOffset(destination_offset);
126 image_copy.setBufferRowLength(0);
127 image_copy.setBufferImageHeight(0);
128 image_copy.setImageSubresource(
129 vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
130 image_copy.setImageOffset(
131 vk::Offset3D(source_region.origin.x, source_region.origin.y, 0));
132 image_copy.setImageExtent(
133 vk::Extent3D(source_region.size.width, source_region.size.height, 1));
134
135 if (!src.SetLayout(barrier)) {
136 VALIDATION_LOG << "Could not encode layout transition.";
137 return false;
138 }
139
140 cmd_buffer.copyImageToBuffer(src.GetImage(), //
141 barrier.new_layout, //
142 dst.GetBuffer(), //
143 image_copy //
144 );
145
146 return true;
147 }
148
149 //------------------------------------------------------------------------------
150 /// BlitCopyBufferToTextureCommandVK
151 ///
152
153 BlitCopyBufferToTextureCommandVK::~BlitCopyBufferToTextureCommandVK() = default;
154
155 std::string BlitCopyBufferToTextureCommandVK::GetLabel() const {
156 return label;
157 }
158
159 bool BlitCopyBufferToTextureCommandVK::Encode(CommandEncoderVK& encoder) const {
160 const auto& cmd_buffer = encoder.GetCommandBuffer();
161
162 // cast destination to TextureVK
163 const auto& dst = TextureVK::Cast(*destination);
164 const auto& src = DeviceBufferVK::Cast(*source.buffer);
165
166 if (!encoder.Track(source.buffer) || !encoder.Track(destination)) {
167 return false;
168 }
169
170 BarrierVK dst_barrier;
171 dst_barrier.cmd_buffer = cmd_buffer;
172 dst_barrier.new_layout = vk::ImageLayout::eTransferDstOptimal;
173 dst_barrier.src_access = {};
174 dst_barrier.src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
175 dst_barrier.dst_access =
176 vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferWrite;
177 dst_barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader |
178 vk::PipelineStageFlagBits::eTransfer;
179
180 vk::BufferImageCopy image_copy;
181 image_copy.setBufferOffset(source.range.offset);
182 image_copy.setBufferRowLength(0);
183 image_copy.setBufferImageHeight(0);
184 image_copy.setImageSubresource(
185 vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
186 image_copy.setImageOffset(
187 vk::Offset3D(destination_origin.x, destination_origin.y, 0));
188 image_copy.setImageExtent(vk::Extent3D(destination->GetSize().width,
189 destination->GetSize().height, 1));
190
191 if (!dst.SetLayout(dst_barrier)) {
192 VALIDATION_LOG << "Could not encode layout transition.";
193 return false;
194 }
195
196 cmd_buffer.copyBufferToImage(src.GetBuffer(), //
197 dst.GetImage(), //
198 dst_barrier.new_layout, //
199 image_copy //
200 );
201
202 return true;
203 }
204
205 //------------------------------------------------------------------------------
206 /// BlitGenerateMipmapCommandVK
207 ///
208
209 BlitGenerateMipmapCommandVK::~BlitGenerateMipmapCommandVK() = default;
210
211 std::string BlitGenerateMipmapCommandVK::GetLabel() const {
212 return label;
213 }
214
215 static void InsertImageMemoryBarrier(const vk::CommandBuffer& cmd,
216 const vk::Image& image,
217 vk::AccessFlags src_access_mask,
218 vk::AccessFlags dst_access_mask,
219 vk::ImageLayout old_layout,
220 vk::ImageLayout new_layout,
221 vk::PipelineStageFlags src_stage,
222 vk::PipelineStageFlags dst_stage,
223 uint32_t base_mip_level,
224 uint32_t mip_level_count = 1u) {
225 if (old_layout == new_layout) {
226 return;
227 }
228
229 vk::ImageMemoryBarrier barrier;
230 barrier.srcAccessMask = src_access_mask;
231 barrier.dstAccessMask = dst_access_mask;
232 barrier.oldLayout = old_layout;
233 barrier.newLayout = new_layout;
234 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
235 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
236 barrier.image = image;
237 barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
238 barrier.subresourceRange.baseMipLevel = base_mip_level;
239 barrier.subresourceRange.levelCount = mip_level_count;
240 barrier.subresourceRange.baseArrayLayer = 0u;
241 barrier.subresourceRange.layerCount = 1u;
242
243 cmd.pipelineBarrier(src_stage, dst_stage, {}, nullptr, nullptr, barrier);
244 }
245
246 bool BlitGenerateMipmapCommandVK::Encode(CommandEncoderVK& encoder) const {
247 auto& src = TextureVK::Cast(*texture);
248
249 const auto size = src.GetTextureDescriptor().size;
250 uint32_t mip_count = src.GetTextureDescriptor().mip_count;
251
252 if (mip_count < 2u) {
253 return true;
254 }
255
256 const auto& image = src.GetImage();
257 const auto& cmd = encoder.GetCommandBuffer();
258
259 if (!encoder.Track(texture)) {
260 return false;
261 }
262
263 // Transition the base mip level to transfer-src layout so we can read from
264 // it and transition the rest to dst-optimal since they are going to be
265 // written to.
266 InsertImageMemoryBarrier(
267 cmd, // command buffer
268 image, // image
269 vk::AccessFlagBits::eTransferWrite, // src access mask
270 vk::AccessFlagBits::eTransferRead, // dst access mask
271 src.GetLayout(), // old layout
272 vk::ImageLayout::eTransferSrcOptimal, // new layout
273 vk::PipelineStageFlagBits::eTransfer, // src stage
274 vk::PipelineStageFlagBits::eTransfer, // dst stage
275 0u // mip level
276 );
277 InsertImageMemoryBarrier(
278 cmd, // command buffer
279 image, // image
280 {}, // src access mask
281 vk::AccessFlagBits::eTransferWrite, // dst access mask
282 vk::ImageLayout::eUndefined, // old layout
283 vk::ImageLayout::eTransferDstOptimal, // new layout
284 vk::PipelineStageFlagBits::eTransfer, // src stage
285 vk::PipelineStageFlagBits::eTransfer, // dst stage
286 1u, // mip level
287 mip_count - 1 // mip level count
288 );
289
290 // Blit from the base mip level to all other levels.
291 for (size_t mip_level = 1u; mip_level < mip_count; mip_level++) {
292 vk::ImageBlit blit;
293
294 blit.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
295 blit.srcSubresource.baseArrayLayer = 0u;
296 blit.srcSubresource.layerCount = 1u;
297 blit.srcSubresource.mipLevel = 0u;
298
299 blit.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
300 blit.dstSubresource.baseArrayLayer = 0u;
301 blit.dstSubresource.layerCount = 1u;
302 blit.dstSubresource.mipLevel = mip_level;
303
304 // offsets[0] is origin.
305 blit.srcOffsets[1].x = size.width;
306 blit.srcOffsets[1].y = size.height;
307 blit.srcOffsets[1].z = 1u;
308
309 // offsets[0] is origin.
310 blit.dstOffsets[1].x = std::max<int32_t>(size.width >> mip_level, 1u);
311 blit.dstOffsets[1].y = std::max<int32_t>(size.height >> mip_level, 1u);
312 blit.dstOffsets[1].z = 1u;
313
314 cmd.blitImage(image, // src image
315 vk::ImageLayout::eTransferSrcOptimal, // src layout
316 image, // dst image
317 vk::ImageLayout::eTransferDstOptimal, // dst layout
318 1u, // region count
319 &blit, // regions
320 vk::Filter::eLinear // filter
321 );
322 }
323
324 // Transition all mip levels to shader read. The base mip level has a
325 // different "old" layout than the rest now.
326 InsertImageMemoryBarrier(
327 cmd, // command buffer
328 image, // image
329 vk::AccessFlagBits::eTransferWrite, // src access mask
330 vk::AccessFlagBits::eShaderRead, // dst access mask
331 vk::ImageLayout::eTransferSrcOptimal, // old layout
332 vk::ImageLayout::eShaderReadOnlyOptimal, // new layout
333 vk::PipelineStageFlagBits::eTransfer, // src stage
334 vk::PipelineStageFlagBits::eFragmentShader, // dst stage
335 0u // mip level
336 );
337 InsertImageMemoryBarrier(
338 cmd, // command buffer
339 image, // image
340 vk::AccessFlagBits::eTransferWrite, // src access mask
341 vk::AccessFlagBits::eShaderRead, // dst access mask
342 vk::ImageLayout::eTransferDstOptimal, // old layout
343 vk::ImageLayout::eShaderReadOnlyOptimal, // new layout
344 vk::PipelineStageFlagBits::eTransfer, // src stage
345 vk::PipelineStageFlagBits::eFragmentShader, // dst stage
346 1u, // mip level
347 mip_count - 1 // mip level count
348 );
349
350 // We modified the layouts of this image from underneath it. Tell it its new
351 // state so it doesn't try to perform redundant transitions under the hood.
352 src.SetLayoutWithoutEncoding(vk::ImageLayout::eShaderReadOnlyOptimal);
353
354 return true;
355 }
356
357 } // namespace impeller
impeller::BarrierVK::dst_access
vk::AccessFlags dst_access
Definition: barrier_vk.h:42
impeller::TRect::size
TSize< Type > size
Definition: rect.h:24
impeller::TPoint::y
Type y
Definition: point.h:24
command_encoder_vk.h
impeller::BarrierVK::new_layout
vk::ImageLayout new_layout
Definition: barrier_vk.h:22
impeller::BarrierVK::cmd_buffer
vk::CommandBuffer cmd_buffer
Definition: barrier_vk.h:21
impeller::BlitGenerateMipmapCommandVK::GetLabel
std::string GetLabel() const override
Definition: blit_command_vk.cc:211
impeller::Range::offset
size_t offset
Definition: range.h:14
impeller::BlitCopyTextureToTextureCommand::destination
std::shared_ptr< Texture > destination
Definition: blit_command.h:19
impeller::BlitGenerateMipmapCommandVK::Encode
bool Encode(CommandEncoderVK &encoder) const override
Definition: blit_command_vk.cc:246
impeller::BufferView::range
Range range
Definition: buffer_view.h:16
impeller::BlitCopyTextureToTextureCommand::destination_origin
IPoint destination_origin
Definition: blit_command.h:21
impeller::BlitCopyTextureToTextureCommandVK::Encode
bool Encode(CommandEncoderVK &encoder) const override
Definition: blit_command_vk.cc:25
impeller::BlitCopyTextureToTextureCommandVK::GetLabel
std::string GetLabel() const override
Definition: blit_command_vk.cc:21
impeller::BlitGenerateMipmapCommand::texture
std::shared_ptr< Texture > texture
Definition: blit_command.h:38
impeller::BlitCopyBufferToTextureCommandVK::Encode
bool Encode(CommandEncoderVK &encoder) const override
Definition: blit_command_vk.cc:159
impeller::BlitCommand::label
std::string label
Definition: blit_command.h:14
impeller::BarrierVK
Defines an operations and memory access barrier on a resource.
Definition: barrier_vk.h:20
impeller::BlitCopyBufferToTextureCommand::source
BufferView source
Definition: blit_command.h:32
impeller::CommandEncoderVK::Track
bool Track(std::shared_ptr< SharedObjectVK > object)
Definition: command_encoder_vk.cc:232
impeller::BufferView::buffer
std::shared_ptr< const Buffer > buffer
Definition: buffer_view.h:14
impeller::BlitCopyTextureToBufferCommand::destination_offset
size_t destination_offset
Definition: blit_command.h:28
impeller::BlitGenerateMipmapCommandVK::~BlitGenerateMipmapCommandVK
~BlitGenerateMipmapCommandVK() override
blit_command_vk.h
impeller::BlitCopyTextureToBufferCommandVK::GetLabel
std::string GetLabel() const override
Definition: blit_command_vk.cc:95
impeller::BarrierVK::src_access
vk::AccessFlags src_access
Definition: barrier_vk.h:32
impeller::BlitCopyTextureToBufferCommand::destination
std::shared_ptr< DeviceBuffer > destination
Definition: blit_command.h:26
impeller::TRect::origin
TPoint< Type > origin
Definition: rect.h:23
impeller::InsertImageMemoryBarrier
static void InsertImageMemoryBarrier(const vk::CommandBuffer &cmd, const vk::Image &image, vk::AccessFlags src_access_mask, vk::AccessFlags dst_access_mask, vk::ImageLayout old_layout, vk::ImageLayout new_layout, vk::PipelineStageFlags src_stage, vk::PipelineStageFlags dst_stage, uint32_t base_mip_level, uint32_t mip_level_count=1u)
Definition: blit_command_vk.cc:215
impeller::BlitCopyTextureToBufferCommandVK::Encode
bool Encode(CommandEncoderVK &encoder) const override
Definition: blit_command_vk.cc:99
impeller::BlitCopyTextureToTextureCommand::source
std::shared_ptr< Texture > source
Definition: blit_command.h:18
impeller::TSize::width
Type width
Definition: size.h:21
texture_vk.h
impeller::TPoint::x
Type x
Definition: point.h:23
impeller::BarrierVK::dst_stage
vk::PipelineStageFlags dst_stage
Definition: barrier_vk.h:37
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::BackendCast< TextureVK, Texture >::Cast
static TextureVK & Cast(Texture &base)
Definition: backend_cast.h:14
impeller::BlitCopyTextureToBufferCommand::source
std::shared_ptr< Texture > source
Definition: blit_command.h:25
impeller::BlitCopyBufferToTextureCommandVK::~BlitCopyBufferToTextureCommandVK
~BlitCopyBufferToTextureCommandVK() override
impeller::BlitCopyTextureToTextureCommand::source_region
IRect source_region
Definition: blit_command.h:20
impeller::TSize::height
Type height
Definition: size.h:22
impeller::BlitCopyBufferToTextureCommand::destination_origin
IPoint destination_origin
Definition: blit_command.h:34
impeller::BlitCopyTextureToBufferCommandVK::~BlitCopyTextureToBufferCommandVK
~BlitCopyTextureToBufferCommandVK() override
impeller::BlitCopyTextureToTextureCommandVK::~BlitCopyTextureToTextureCommandVK
~BlitCopyTextureToTextureCommandVK() override
impeller::CommandEncoderVK
Definition: command_encoder_vk.h:45
impeller
Definition: aiks_context.cc:10
impeller::BlitCopyTextureToBufferCommand::source_region
IRect source_region
Definition: blit_command.h:27
impeller::BlitEncodeVK::~BlitEncodeVK
virtual ~BlitEncodeVK()
impeller::CommandEncoderVK::GetCommandBuffer
vk::CommandBuffer GetCommandBuffer() const
Definition: command_encoder_vk.cc:218
impeller::BarrierVK::src_stage
vk::PipelineStageFlags src_stage
Definition: barrier_vk.h:27
impeller::BlitCopyBufferToTextureCommand::destination
std::shared_ptr< Texture > destination
Definition: blit_command.h:33
impeller::BlitCopyBufferToTextureCommandVK::GetLabel
std::string GetLabel() const override
Definition: blit_command_vk.cc:155