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