Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
12#include "vulkan/vulkan_structs.hpp"
13
14namespace impeller {
15
16ComputePassVK::ComputePassVK(std::shared_ptr<const Context> context,
17 std::shared_ptr<CommandBufferVK> command_buffer)
18 : ComputePass(std::move(context)),
19 command_buffer_(std::move(command_buffer)) {
20 is_valid_ = true;
21}
22
23ComputePassVK::~ComputePassVK() = default;
24
25bool ComputePassVK::IsValid() const {
26 return is_valid_;
27}
28
29void ComputePassVK::OnSetLabel(const std::string& label) {
30 if (label.empty()) {
31 return;
32 }
33 label_ = label;
34}
35
36// |RenderPass|
37void ComputePassVK::SetCommandLabel(std::string_view label) {
38#ifdef IMPELLER_DEBUG
39 command_buffer_->PushDebugGroup(label);
40 has_label_ = true;
41#endif // IMPELLER_DEBUG
42}
43
44// |ComputePass|
45void ComputePassVK::SetPipeline(
46 const std::shared_ptr<Pipeline<ComputePipelineDescriptor>>& pipeline) {
47 const auto& pipeline_vk = ComputePipelineVK::Cast(*pipeline);
48 const vk::CommandBuffer& command_buffer_vk =
49 command_buffer_->GetCommandBuffer();
50 command_buffer_vk.bindPipeline(vk::PipelineBindPoint::eCompute,
51 pipeline_vk.GetPipeline());
52 pipeline_layout_ = pipeline_vk.GetPipelineLayout();
53
54 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
55 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
56 ContextVK::Cast(*context_));
57 if (!descriptor_result.ok()) {
58 return;
59 }
60 descriptor_set_ = descriptor_result.value();
61 pipeline_valid_ = true;
62}
63
64// |ComputePass|
65fml::Status ComputePassVK::Compute(std::array<uint32_t, 3> workgroup_count) {
66 if (workgroup_count[0] == 0u || workgroup_count[1] == 0u ||
67 workgroup_count[2] == 0u || !pipeline_valid_) {
68 bound_image_offset_ = 0u;
69 bound_buffer_offset_ = 0u;
70 descriptor_write_offset_ = 0u;
71 has_label_ = false;
72 pipeline_valid_ = false;
74 "Invalid pipeline or empty workgroup count.");
75 }
76
77 const ContextVK& context_vk = ContextVK::Cast(*context_);
78 for (auto i = 0u; i < descriptor_write_offset_; i++) {
79 write_workspace_[i].dstSet = descriptor_set_;
80 }
81
82 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
83 write_workspace_.data(), 0u, {});
84 const vk::CommandBuffer& command_buffer_vk =
85 command_buffer_->GetCommandBuffer();
86
87 command_buffer_vk.bindDescriptorSets(
88 vk::PipelineBindPoint::eCompute, // bind point
89 pipeline_layout_, // layout
90 0, // first set
91 1, // set count
92 &descriptor_set_, // sets
93 0, // offset count
94 nullptr // offsets
95 );
96
97 // The arguments are workgroup counts. The per-workgroup invocation count (the
98 // local size) is baked into the shader module, so dispatch the counts
99 // directly.
100 command_buffer_vk.dispatch(workgroup_count[0], workgroup_count[1],
101 workgroup_count[2]);
102
103#ifdef IMPELLER_DEBUG
104 if (has_label_) {
105 command_buffer_->PopDebugGroup();
106 }
107 has_label_ = false;
108#endif // IMPELLER_DEBUG
109
110 bound_image_offset_ = 0u;
111 bound_buffer_offset_ = 0u;
112 descriptor_write_offset_ = 0u;
113 has_label_ = false;
114 pipeline_valid_ = false;
115
116 return fml::Status();
117}
118
119// |ResourceBinder|
120bool ComputePassVK::BindResource(ShaderStage stage,
121 DescriptorType type,
122 const ShaderUniformSlot& slot,
123 const ShaderMetadata* metadata,
124 BufferView view) {
125 return BindResource(slot.binding, type, view);
126}
127
128// |ResourceBinder|
129bool ComputePassVK::BindResource(ShaderStage stage,
130 DescriptorType type,
131 const SampledImageSlot& slot,
132 const ShaderMetadata* metadata,
133 std::shared_ptr<const Texture> texture,
134 raw_ptr<const Sampler> sampler) {
135 if (bound_image_offset_ >= kMaxBindings) {
136 return false;
137 }
138 if (!texture->IsValid() || !sampler) {
139 return false;
140 }
141 const TextureVK& texture_vk = TextureVK::Cast(*texture);
142 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
143
144 if (!command_buffer_->Track(texture)) {
145 return false;
146 }
147
148 vk::DescriptorImageInfo image_info;
149 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
150 image_info.sampler = sampler_vk.GetSampler();
151 image_info.imageView = texture_vk.GetImageView();
152 image_workspace_[bound_image_offset_++] = image_info;
153
154 vk::WriteDescriptorSet write_set;
155 write_set.dstBinding = slot.binding;
156 write_set.descriptorCount = 1u;
157 write_set.descriptorType = ToVKDescriptorType(type);
158 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
159
160 write_workspace_[descriptor_write_offset_++] = write_set;
161 return true;
162}
163
164bool ComputePassVK::BindResource(size_t binding,
165 DescriptorType type,
166 BufferView view) {
167 if (bound_buffer_offset_ >= kMaxBindings) {
168 return false;
169 }
170
171 auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
172 if (!buffer) {
173 return false;
174 }
175
176 std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
177 if (device_buffer && !command_buffer_->Track(device_buffer)) {
178 return false;
179 }
180
181 uint32_t offset = view.GetRange().offset;
182
183 vk::DescriptorBufferInfo buffer_info;
184 buffer_info.buffer = buffer;
185 buffer_info.offset = offset;
186 buffer_info.range = view.GetRange().length;
187 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
188
189 vk::WriteDescriptorSet write_set;
190 write_set.dstBinding = binding;
191 write_set.descriptorCount = 1u;
192 write_set.descriptorType = ToVKDescriptorType(type);
193 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
194
195 write_workspace_[descriptor_write_offset_++] = write_set;
196 return true;
197}
198
199// Note:
200// https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples
201// Seems to suggest that anything more finely grained than a global memory
202// barrier is likely to be weakened into a global barrier. Confirming this on
203// mobile devices will require some experimentation.
204
205// |ComputePass|
206void ComputePassVK::AddBufferMemoryBarrier() {
207 vk::MemoryBarrier barrier;
208 barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
209 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
210
211 command_buffer_->GetCommandBuffer().pipelineBarrier(
212 vk::PipelineStageFlagBits::eComputeShader,
213 vk::PipelineStageFlagBits::eComputeShader, {}, 1, &barrier, 0, {}, 0, {});
214}
215
216// |ComputePass|
217void ComputePassVK::AddTextureMemoryBarrier() {
218 vk::MemoryBarrier barrier;
219 barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
220 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
221
222 command_buffer_->GetCommandBuffer().pipelineBarrier(
223 vk::PipelineStageFlagBits::eComputeShader,
224 vk::PipelineStageFlagBits::eComputeShader, {}, 1, &barrier, 0, {}, 0, {});
225}
226
227// |ComputePass|
228bool ComputePassVK::EncodeCommands() const {
229 // Since we only use global memory barrier, we don't have to worry about
230 // compute to compute dependencies across cmd buffers. Instead, we pessimize
231 // here and assume that we wrote to a storage image or buffer and that a
232 // render pass will read from it. if there are ever scenarios where we end up
233 // with compute to compute dependencies this should be revisited.
234
235 // This does not currently handle image barriers as we do not use them
236 // for anything.
237 vk::MemoryBarrier barrier;
238 barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
239 barrier.dstAccessMask =
240 vk::AccessFlagBits::eIndexRead | vk::AccessFlagBits::eVertexAttributeRead;
241
242 command_buffer_->GetCommandBuffer().pipelineBarrier(
243 vk::PipelineStageFlagBits::eComputeShader,
244 vk::PipelineStageFlagBits::eVertexInput, {}, 1, &barrier, 0, {}, 0, {});
245
246 return true;
247}
248
249} // namespace impeller
FlView * view
FlTexture * texture
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition formats_vk.h:328
Definition ref_ptr.h:261
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
std::shared_ptr< CommandBuffer > command_buffer
impeller::ShaderType type