12 #include "vulkan/vulkan_structs.hpp"
16 ComputePassVK::ComputePassVK(std::shared_ptr<const Context>
context,
23 ComputePassVK::~ComputePassVK() =
default;
25 bool ComputePassVK::IsValid()
const {
29 void ComputePassVK::OnSetLabel(
const std::string& label) {
37 void ComputePassVK::SetCommandLabel(std::string_view label) {
39 command_buffer_->PushDebugGroup(label);
45 void 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();
54 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
55 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
56 ContextVK::Cast(*context_));
57 if (!descriptor_result.ok()) {
60 descriptor_set_ = descriptor_result.value();
61 pipeline_valid_ =
true;
65 fml::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;
72 pipeline_valid_ =
false;
73 return fml::Status(fml::StatusCode::kCancelled,
74 "Invalid pipeline or empty workgroup count.");
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_;
82 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
83 write_workspace_.data(), 0u, {});
84 const vk::CommandBuffer& command_buffer_vk =
85 command_buffer_->GetCommandBuffer();
87 command_buffer_vk.bindDescriptorSets(
88 vk::PipelineBindPoint::eCompute,
100 command_buffer_vk.dispatch(workgroup_count[0], workgroup_count[1],
103 #ifdef IMPELLER_DEBUG
105 command_buffer_->PopDebugGroup();
110 bound_image_offset_ = 0u;
111 bound_buffer_offset_ = 0u;
112 descriptor_write_offset_ = 0u;
114 pipeline_valid_ =
false;
116 return fml::Status();
120 bool ComputePassVK::BindResource(
ShaderStage stage,
122 const ShaderUniformSlot& slot,
123 const ShaderMetadata* metadata,
125 return BindResource(slot.binding, type, view);
129 bool ComputePassVK::BindResource(
ShaderStage stage,
131 const SampledImageSlot& slot,
132 const ShaderMetadata* metadata,
133 std::shared_ptr<const Texture> texture,
134 raw_ptr<const Sampler> sampler) {
138 if (!texture->IsValid() || !sampler) {
141 const TextureVK& texture_vk = TextureVK::Cast(*texture);
142 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
144 if (!command_buffer_->Track(texture)) {
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;
154 vk::WriteDescriptorSet write_set;
155 write_set.dstBinding = slot.binding;
156 write_set.descriptorCount = 1u;
158 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
160 write_workspace_[descriptor_write_offset_++] = write_set;
164 bool ComputePassVK::BindResource(
size_t binding,
171 auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
176 std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
177 if (device_buffer && !command_buffer_->Track(device_buffer)) {
181 uint32_t offset = view.GetRange().offset;
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;
189 vk::WriteDescriptorSet write_set;
190 write_set.dstBinding = binding;
191 write_set.descriptorCount = 1u;
193 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
195 write_workspace_[descriptor_write_offset_++] = write_set;
206 void ComputePassVK::AddBufferMemoryBarrier() {
207 vk::MemoryBarrier barrier;
208 barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
209 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
211 command_buffer_->GetCommandBuffer().pipelineBarrier(
212 vk::PipelineStageFlagBits::eComputeShader,
213 vk::PipelineStageFlagBits::eComputeShader, {}, 1, &barrier, 0, {}, 0, {});
217 void ComputePassVK::AddTextureMemoryBarrier() {
218 vk::MemoryBarrier barrier;
219 barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
220 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
222 command_buffer_->GetCommandBuffer().pipelineBarrier(
223 vk::PipelineStageFlagBits::eComputeShader,
224 vk::PipelineStageFlagBits::eComputeShader, {}, 1, &barrier, 0, {}, 0, {});
228 bool ComputePassVK::EncodeCommands()
const {
237 vk::MemoryBarrier barrier;
238 barrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
239 barrier.dstAccessMask =
240 vk::AccessFlagBits::eIndexRead | vk::AccessFlagBits::eVertexAttributeRead;
242 command_buffer_->GetCommandBuffer().pipelineBarrier(
243 vk::PipelineStageFlagBits::eComputeShader,
244 vk::PipelineStageFlagBits::eVertexInput, {}, 1, &barrier, 0, {}, 0, {});
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
static constexpr size_t kMaxBindings
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
std::shared_ptr< CommandBuffer > command_buffer