| 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 <cstdint>
8
9 #include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
10 #include "impeller/renderer/backend/vulkan/texture_vk.h"
11
12 namespace impeller {
13
14 BlitEncodeVK::~BlitEncodeVK() = default;
15
16 //------------------------------------------------------------------------------
17 /// BlitCopyTextureToTextureCommandVK
18 ///
19
20 BlitCopyTextureToTextureCommandVK::~BlitCopyTextureToTextureCommandVK() =
21 default;
22
23 std::string BlitCopyTextureToTextureCommandVK::GetLabel() const {
24 return label;
25 }
26
27 bool BlitCopyTextureToTextureCommandVK::Encode(
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
95 BlitCopyTextureToBufferCommandVK::~BlitCopyTextureToBufferCommandVK() = default;
96
97 std::string BlitCopyTextureToBufferCommandVK::GetLabel() const {
98 return label;
99 }
100
101 bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const {
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
155 BlitCopyBufferToTextureCommandVK::~BlitCopyBufferToTextureCommandVK() = default;
156
157 std::string BlitCopyBufferToTextureCommandVK::GetLabel() const {
158 return label;
159 }
160
161 bool BlitCopyBufferToTextureCommandVK::Encode(CommandEncoderVK& encoder) const {
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
211 BlitGenerateMipmapCommandVK::~BlitGenerateMipmapCommandVK() = default;
212
213 std::string BlitGenerateMipmapCommandVK::GetLabel() const {
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
248 bool BlitGenerateMipmapCommandVK::Encode(CommandEncoderVK& encoder) const {
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.
268 InsertImageMemoryBarrier(
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 );
279 InsertImageMemoryBarrier(
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.
328 InsertImageMemoryBarrier(
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 );
339 InsertImageMemoryBarrier(
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