| 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
5 #include "impeller/renderer/backend/vulkan/compute_pass_vk.h"
6
7 #include "flutter/fml/trace_event.h"
8 #include "impeller/renderer/backend/vulkan/binding_helpers_vk.h"
9 #include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
10 #include "impeller/renderer/backend/vulkan/compute_pipeline_vk.h"
11 #include "impeller/renderer/backend/vulkan/texture_vk.h"
12 #include "impeller/renderer/command.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
23 ComputePassVK::~ComputePassVK() = default;
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