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 
6 
9 
10 namespace impeller {
11 
12 BlitEncodeVK::~BlitEncodeVK() = default;
13 
14 //------------------------------------------------------------------------------
15 /// BlitCopyTextureToTextureCommandVK
16 ///
17 
19  default;
20 
22  return label;
23 }
24 
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 
94 
96  return label;
97 }
98 
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 
154 
156  return label;
157 }
158 
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 
210 
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 
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.
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  );
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.
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  );
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