Flutter Impeller
compute_pass_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 "flutter/fml/trace_event.h"
13 
14 namespace impeller {
15 
16 ComputePassVK::ComputePassVK(std::weak_ptr<const Context> context,
17  std::weak_ptr<CommandBufferVK> command_buffer)
18  : ComputePass(std::move(context)),
19  command_buffer_(std::move(command_buffer)) {
20  is_valid_ = true;
21 }
22 
24 
25 bool ComputePassVK::IsValid() const {
26  return is_valid_;
27 }
28 
29 void ComputePassVK::OnSetLabel(const std::string& label) {
30  if (label.empty()) {
31  return;
32  }
33  label_ = label;
34 }
35 
36 static bool UpdateBindingLayouts(const Bindings& bindings,
37  const vk::CommandBuffer& buffer) {
38  BarrierVK barrier;
39  barrier.cmd_buffer = buffer;
40  barrier.src_access = vk::AccessFlagBits::eTransferWrite;
41  barrier.src_stage = vk::PipelineStageFlagBits::eTransfer;
42  barrier.dst_access = vk::AccessFlagBits::eShaderRead;
43  barrier.dst_stage = vk::PipelineStageFlagBits::eComputeShader;
44 
45  barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
46 
47  for (const TextureAndSampler& data : bindings.sampled_images) {
48  if (!TextureVK::Cast(*data.texture.resource).SetLayout(barrier)) {
49  return false;
50  }
51  }
52  return true;
53 }
54 
55 static bool UpdateBindingLayouts(const ComputeCommand& command,
56  const vk::CommandBuffer& buffer) {
57  return UpdateBindingLayouts(command.bindings, buffer);
58 }
59 
60 static bool UpdateBindingLayouts(const std::vector<ComputeCommand>& commands,
61  const vk::CommandBuffer& buffer) {
62  for (const ComputeCommand& command : commands) {
63  if (!UpdateBindingLayouts(command, buffer)) {
64  return false;
65  }
66  }
67  return true;
68 }
69 
70 bool ComputePassVK::OnEncodeCommands(const Context& context,
71  const ISize& grid_size,
72  const ISize& thread_group_size) const {
73  TRACE_EVENT0("impeller", "ComputePassVK::EncodeCommands");
74  if (!IsValid()) {
75  return false;
76  }
77 
78  FML_DCHECK(!grid_size.IsEmpty() && !thread_group_size.IsEmpty());
79 
80  const auto& vk_context = ContextVK::Cast(context);
81  auto command_buffer = command_buffer_.lock();
82  if (!command_buffer) {
83  VALIDATION_LOG << "Command buffer died before commands could be encoded.";
84  return false;
85  }
86  auto encoder = command_buffer->GetEncoder();
87  if (!encoder) {
88  return false;
89  }
90 
91  fml::ScopedCleanupClosure pop_marker(
92  [&encoder]() { encoder->PopDebugGroup(); });
93  if (!label_.empty()) {
94  encoder->PushDebugGroup(label_.c_str());
95  } else {
96  pop_marker.Release();
97  }
98  auto cmd_buffer = encoder->GetCommandBuffer();
99 
100  if (!UpdateBindingLayouts(commands_, cmd_buffer)) {
101  VALIDATION_LOG << "Could not update binding layouts for compute pass.";
102  return false;
103  }
104  auto desc_sets_result =
105  AllocateAndBindDescriptorSets(vk_context, encoder, commands_);
106  if (!desc_sets_result.ok()) {
107  return false;
108  }
109  auto desc_sets = desc_sets_result.value();
110 
111  TRACE_EVENT0("impeller", "EncodeComputePassCommands");
112  size_t desc_index = 0;
113  for (const auto& command : commands_) {
114  const auto& pipeline_vk = ComputePipelineVK::Cast(*command.pipeline);
115 
116  cmd_buffer.bindPipeline(vk::PipelineBindPoint::eCompute,
117  pipeline_vk.GetPipeline());
118  cmd_buffer.bindDescriptorSets(
119  vk::PipelineBindPoint::eCompute, // bind point
120  pipeline_vk.GetPipelineLayout(), // layout
121  0, // first set
122  {vk::DescriptorSet{desc_sets[desc_index]}}, // sets
123  nullptr // offsets
124  );
125 
126  // TOOD(dnfield): This should be moved to caps. But for now keeping this
127  // in parallel with Metal.
128  auto device_properties = vk_context.GetPhysicalDevice().getProperties();
129 
130  auto max_wg_size = device_properties.limits.maxComputeWorkGroupSize;
131 
132  int64_t width = grid_size.width;
133  int64_t height = grid_size.height;
134 
135  // Special case for linear processing.
136  if (height == 1) {
137  int64_t minimum = 1;
138  int64_t threadGroups = std::max(
139  static_cast<int64_t>(std::ceil(width * 1.0 / max_wg_size[0] * 1.0)),
140  minimum);
141  cmd_buffer.dispatch(threadGroups, 1, 1);
142  } else {
143  while (width > max_wg_size[0]) {
144  width = std::max(static_cast<int64_t>(1), width / 2);
145  }
146  while (height > max_wg_size[1]) {
147  height = std::max(static_cast<int64_t>(1), height / 2);
148  }
149  cmd_buffer.dispatch(width, height, 1);
150  }
151  desc_index += 1;
152  }
153 
154  return true;
155 }
156 
157 } // namespace impeller
impeller::BarrierVK::dst_access
vk::AccessFlags dst_access
Definition: barrier_vk.h:43
impeller::Resource::resource
ResourceType resource
Definition: command.h:34
impeller::AllocateAndBindDescriptorSets
fml::StatusOr< std::vector< vk::DescriptorSet > > AllocateAndBindDescriptorSets(const ContextVK &context, const std::shared_ptr< CommandEncoderVK > &encoder, const std::vector< Command > &commands, const TextureVK &input_attachment)
Definition: binding_helpers_vk.cc:123
compute_pass_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::ComputePassVK::~ComputePassVK
~ComputePassVK() override
impeller::Bindings::sampled_images
std::vector< TextureAndSampler > sampled_images
Definition: command.h:74
impeller::ComputePass::commands_
std::vector< ComputeCommand > commands_
Definition: compute_pass.h:60
impeller::UpdateBindingLayouts
static bool UpdateBindingLayouts(const Bindings &bindings, const vk::CommandBuffer &buffer)
Definition: compute_pass_vk.cc:36
impeller::TextureVK::SetLayout
bool SetLayout(const BarrierVK &barrier) const
Definition: texture_vk.cc:140
command.h
command_buffer_vk.h
impeller::BarrierVK
Defines an operations and memory access barrier on a resource.
Definition: barrier_vk.h:21
compute_pipeline_vk.h
impeller::ComputeCommand::bindings
Bindings bindings
Definition: compute_command.h:45
impeller::BarrierVK::src_access
vk::AccessFlags src_access
Definition: barrier_vk.h:33
texture_vk.h
impeller::TextureAndSampler
combines the texture, sampler and sampler slot information.
Definition: command.h:61
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::BarrierVK::dst_stage
vk::PipelineStageFlags dst_stage
Definition: barrier_vk.h:38
impeller::TextureAndSampler::texture
TextureResource texture
Definition: command.h:63
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:67
impeller::ComputeCommand
An object used to specify compute work to the GPU along with references to resources the GPU will use...
Definition: compute_command.h:36
std
Definition: comparable.h:95
binding_helpers_vk.h
impeller::BackendCast< TextureVK, Texture >::Cast
static TextureVK & Cast(Texture &base)
Definition: backend_cast.h:15
impeller
Definition: aiks_context.cc:10
impeller::BarrierVK::src_stage
vk::PipelineStageFlags src_stage
Definition: barrier_vk.h:28
impeller::Bindings
Definition: command.h:73