Flutter Impeller
impeller::PipelineVK Class Referencefinal

#include <pipeline_vk.h>

Inheritance diagram for impeller::PipelineVK:
impeller::Pipeline< PipelineDescriptor > impeller::BackendCast< PipelineVK, Pipeline< PipelineDescriptor > >

Public Member Functions

 ~PipelineVK () override
 
vk::Pipeline GetPipeline () const
 
const vk::PipelineLayout & GetPipelineLayout () const
 
const vk::DescriptorSetLayout & GetDescriptorSetLayout () const
 
std::shared_ptr< PipelineVKCreateVariantForImmutableSamplers (const std::shared_ptr< SamplerVK > &immutable_sampler) const
 
- Public Member Functions inherited from impeller::Pipeline< PipelineDescriptor >
virtual ~Pipeline ()
 
virtual bool IsValid () const=0
 
const PipelineDescriptorGetDescriptor () const
 Get the descriptor that was responsible for creating this pipeline. It may be copied and modified to create a pipeline variant. More...
 
PipelineFuture< PipelineDescriptorCreateVariant (std::function< void(PipelineDescriptor &desc)> descriptor_callback) const
 

Static Public Member Functions

static std::unique_ptr< PipelineVKCreate (const PipelineDescriptor &desc, const std::shared_ptr< DeviceHolderVK > &device_holder, const std::weak_ptr< PipelineLibrary > &weak_library, std::shared_ptr< SamplerVK > immutable_sampler={})
 
- Static Public Member Functions inherited from impeller::BackendCast< PipelineVK, Pipeline< PipelineDescriptor > >
static PipelineVKCast (Pipeline< PipelineDescriptor > &base)
 
static const PipelineVKCast (const Pipeline< PipelineDescriptor > &base)
 
static PipelineVKCast (Pipeline< PipelineDescriptor > *base)
 
static const PipelineVKCast (const Pipeline< PipelineDescriptor > *base)
 

Friends

class PipelineLibraryVK
 

Additional Inherited Members

- Protected Member Functions inherited from impeller::Pipeline< PipelineDescriptor >
 Pipeline (std::weak_ptr< PipelineLibrary > library, PipelineDescriptor desc)
 
- Protected Attributes inherited from impeller::Pipeline< PipelineDescriptor >
const std::weak_ptr< PipelineLibrarylibrary_
 
const PipelineDescriptor desc_
 

Detailed Description

Definition at line 28 of file pipeline_vk.h.

Constructor & Destructor Documentation

◆ ~PipelineVK()

impeller::PipelineVK::~PipelineVK ( )
override

Definition at line 484 of file pipeline_vk.cc.

484  {
485  if (auto device = device_holder_.lock(); !device) {
486  descriptor_set_layout_.release();
487  layout_.release();
488  render_pass_.release();
489  pipeline_.release();
490  }
491 }

Member Function Documentation

◆ Create()

std::unique_ptr< PipelineVK > impeller::PipelineVK::Create ( const PipelineDescriptor desc,
const std::shared_ptr< DeviceHolderVK > &  device_holder,
const std::weak_ptr< PipelineLibrary > &  weak_library,
std::shared_ptr< SamplerVK immutable_sampler = {} 
)
static

Dynamic States

Viewport State

Shader Stages

Rasterization State

Multi-sample State

Primitive Input Assembly State

Color Blend State

Vertex Input Setup

Pipeline Layout a.k.a the descriptor sets and uniforms.

Create the pipeline layout.

Create the depth stencil state.

Setup the optional pipeline creation feedback struct so we can understand how Vulkan created the PSO.

Finally, all done with the setup info. Create the pipeline itself.

Definition at line 167 of file pipeline_vk.cc.

171  {
172  TRACE_EVENT0("flutter", "PipelineVK::Create");
173 
174  auto library = weak_library.lock();
175 
176  if (!device_holder || !library) {
177  return nullptr;
178  }
179 
180  const auto& pso_cache = PipelineLibraryVK::Cast(*library).GetPSOCache();
181 
182  vk::StructureChain<vk::GraphicsPipelineCreateInfo,
183  vk::PipelineCreationFeedbackCreateInfoEXT>
184  chain;
185 
186  const auto* caps = pso_cache->GetCapabilities();
187 
188  const auto supports_pipeline_creation_feedback = caps->HasExtension(
190  if (!supports_pipeline_creation_feedback) {
191  chain.unlink<vk::PipelineCreationFeedbackCreateInfoEXT>();
192  }
193 
194  auto& pipeline_info = chain.get<vk::GraphicsPipelineCreateInfo>();
195 
196  //----------------------------------------------------------------------------
197  /// Dynamic States
198  ///
199  vk::PipelineDynamicStateCreateInfo dynamic_create_state_info;
200  std::vector<vk::DynamicState> dynamic_states = {
201  vk::DynamicState::eViewport,
202  vk::DynamicState::eScissor,
203  vk::DynamicState::eStencilReference,
204  };
205  dynamic_create_state_info.setDynamicStates(dynamic_states);
206  pipeline_info.setPDynamicState(&dynamic_create_state_info);
207 
208  //----------------------------------------------------------------------------
209  /// Viewport State
210  ///
211  vk::PipelineViewportStateCreateInfo viewport_state;
212  viewport_state.setViewportCount(1u);
213  viewport_state.setScissorCount(1u);
214  // The actual viewport and scissor rects are not set here since they are
215  // dynamic as mentioned above in the dynamic state info.
216  pipeline_info.setPViewportState(&viewport_state);
217 
218  //----------------------------------------------------------------------------
219  /// Shader Stages
220  ///
221  const auto& constants = desc.GetSpecializationConstants();
222 
223  std::vector<std::vector<vk::SpecializationMapEntry>> map_entries(
224  desc.GetStageEntrypoints().size());
225  std::vector<vk::SpecializationInfo> specialization_infos(
226  desc.GetStageEntrypoints().size());
227  std::vector<vk::PipelineShaderStageCreateInfo> shader_stages;
228 
229  size_t entrypoint_count = 0;
230  for (const auto& entrypoint : desc.GetStageEntrypoints()) {
231  auto stage = ToVKShaderStageFlagBits(entrypoint.first);
232  if (!stage.has_value()) {
233  VALIDATION_LOG << "Unsupported shader type in pipeline: "
234  << desc.GetLabel();
235  return nullptr;
236  }
237 
238  std::vector<vk::SpecializationMapEntry>& entries =
239  map_entries[entrypoint_count];
240  for (auto i = 0u; i < constants.size(); i++) {
241  vk::SpecializationMapEntry entry;
242  entry.offset = (i * sizeof(Scalar));
243  entry.size = sizeof(Scalar);
244  entry.constantID = i;
245  entries.emplace_back(entry);
246  }
247 
248  vk::SpecializationInfo& specialization_info =
249  specialization_infos[entrypoint_count];
250  specialization_info.setMapEntries(map_entries[entrypoint_count]);
251  specialization_info.setPData(constants.data());
252  specialization_info.setDataSize(sizeof(Scalar) * constants.size());
253 
254  vk::PipelineShaderStageCreateInfo info;
255  info.setStage(stage.value());
256  info.setPName("main");
257  info.setModule(
258  ShaderFunctionVK::Cast(entrypoint.second.get())->GetModule());
259  info.setPSpecializationInfo(&specialization_info);
260  shader_stages.push_back(info);
261  entrypoint_count++;
262  }
263  pipeline_info.setStages(shader_stages);
264 
265  //----------------------------------------------------------------------------
266  /// Rasterization State
267  ///
268  vk::PipelineRasterizationStateCreateInfo rasterization_state;
269  rasterization_state.setFrontFace(ToVKFrontFace(desc.GetWindingOrder()));
270  rasterization_state.setCullMode(ToVKCullModeFlags(desc.GetCullMode()));
271  rasterization_state.setPolygonMode(ToVKPolygonMode(desc.GetPolygonMode()));
272  rasterization_state.setLineWidth(1.0f);
273  rasterization_state.setDepthClampEnable(false);
274  rasterization_state.setRasterizerDiscardEnable(false);
275  pipeline_info.setPRasterizationState(&rasterization_state);
276 
277  //----------------------------------------------------------------------------
278  /// Multi-sample State
279  ///
280  vk::PipelineMultisampleStateCreateInfo multisample_state;
281  multisample_state.setRasterizationSamples(
282  ToVKSampleCountFlagBits(desc.GetSampleCount()));
283  pipeline_info.setPMultisampleState(&multisample_state);
284 
285  //----------------------------------------------------------------------------
286  /// Primitive Input Assembly State
287  vk::PipelineInputAssemblyStateCreateInfo input_assembly;
288  const auto topology = ToVKPrimitiveTopology(desc.GetPrimitiveType());
289  input_assembly.setTopology(topology);
290  pipeline_info.setPInputAssemblyState(&input_assembly);
291 
292  //----------------------------------------------------------------------------
293  /// Color Blend State
294  std::vector<vk::PipelineColorBlendAttachmentState> attachment_blend_state;
295  for (const auto& color_desc : desc.GetColorAttachmentDescriptors()) {
296  // TODO(csg): The blend states are per color attachment. But it isn't clear
297  // how the color attachment indices are specified in the pipeline create
298  // info. But, this should always work for one color attachment.
299  attachment_blend_state.push_back(
300  ToVKPipelineColorBlendAttachmentState(color_desc.second));
301  }
302  vk::PipelineColorBlendStateCreateInfo blend_state;
303  blend_state.setAttachments(attachment_blend_state);
304  pipeline_info.setPColorBlendState(&blend_state);
305 
306  auto render_pass =
307  CreateCompatRenderPassForPipeline(device_holder->GetDevice(), //
308  desc //
309  );
310 
311  if (!render_pass) {
312  VALIDATION_LOG << "Could not create render pass for pipeline.";
313  return nullptr;
314  }
315 
316  // Convention wisdom says that the base acceleration pipelines are never used
317  // by drivers for cache hits. Instead, the PSO cache is the preferred
318  // mechanism.
319  pipeline_info.setBasePipelineHandle(VK_NULL_HANDLE);
320  pipeline_info.setSubpass(0u);
321  pipeline_info.setRenderPass(render_pass.get());
322 
323  //----------------------------------------------------------------------------
324  /// Vertex Input Setup
325  ///
326  std::vector<vk::VertexInputAttributeDescription> attr_descs;
327  std::vector<vk::VertexInputBindingDescription> buffer_descs;
328 
329  const auto& stage_inputs = desc.GetVertexDescriptor()->GetStageInputs();
330  const auto& stage_buffer_layouts =
331  desc.GetVertexDescriptor()->GetStageLayouts();
332  for (const ShaderStageIOSlot& stage_in : stage_inputs) {
333  vk::VertexInputAttributeDescription attr_desc;
334  attr_desc.setBinding(stage_in.binding);
335  attr_desc.setLocation(stage_in.location);
336  attr_desc.setFormat(ToVertexDescriptorFormat(stage_in));
337  attr_desc.setOffset(stage_in.offset);
338  attr_descs.push_back(attr_desc);
339  }
340  for (const ShaderStageBufferLayout& layout : stage_buffer_layouts) {
341  vk::VertexInputBindingDescription binding_description;
342  binding_description.setBinding(layout.binding);
343  binding_description.setInputRate(vk::VertexInputRate::eVertex);
344  binding_description.setStride(layout.stride);
345  buffer_descs.push_back(binding_description);
346  }
347 
348  vk::PipelineVertexInputStateCreateInfo vertex_input_state;
349  vertex_input_state.setVertexAttributeDescriptions(attr_descs);
350  vertex_input_state.setVertexBindingDescriptions(buffer_descs);
351 
352  pipeline_info.setPVertexInputState(&vertex_input_state);
353 
354  //----------------------------------------------------------------------------
355  /// Pipeline Layout a.k.a the descriptor sets and uniforms.
356  ///
357  std::vector<vk::DescriptorSetLayoutBinding> set_bindings;
358 
359  vk::Sampler vk_immutable_sampler =
360  immutable_sampler ? immutable_sampler->GetSampler()
361  : static_cast<vk::Sampler>(VK_NULL_HANDLE);
362 
363  for (auto layout : desc.GetVertexDescriptor()->GetDescriptorSetLayouts()) {
364  vk::DescriptorSetLayoutBinding set_binding;
365  set_binding.binding = layout.binding;
366  set_binding.descriptorCount = 1u;
367  set_binding.descriptorType = ToVKDescriptorType(layout.descriptor_type);
368  set_binding.stageFlags = ToVkShaderStage(layout.shader_stage);
369  // TODO(143719): This specifies the immutable sampler for all sampled
370  // images. This is incorrect. In cases where the shader samples from the
371  // multiple images, there is currently no way to tell which sampler needs to
372  // be immutable and which one needs a binding set in the render pass. Expect
373  // errors if the shader has more than on sampled image. The sampling from
374  // the one that is expected to be non-immutable will be incorrect.
375  if (vk_immutable_sampler &&
376  layout.descriptor_type == DescriptorType::kSampledImage) {
377  set_binding.setImmutableSamplers(vk_immutable_sampler);
378  }
379  set_bindings.push_back(set_binding);
380  }
381 
382  vk::DescriptorSetLayoutCreateInfo desc_set_layout_info;
383  desc_set_layout_info.setBindings(set_bindings);
384 
385  auto [descs_result, descs_layout] =
386  device_holder->GetDevice().createDescriptorSetLayoutUnique(
387  desc_set_layout_info);
388  if (descs_result != vk::Result::eSuccess) {
389  VALIDATION_LOG << "unable to create uniform descriptors";
390  return nullptr;
391  }
392 
393  ContextVK::SetDebugName(device_holder->GetDevice(), descs_layout.get(),
394  "Descriptor Set Layout " + desc.GetLabel());
395 
396  //----------------------------------------------------------------------------
397  /// Create the pipeline layout.
398  ///
399  vk::PipelineLayoutCreateInfo pipeline_layout_info;
400  pipeline_layout_info.setSetLayouts(descs_layout.get());
401  auto pipeline_layout = device_holder->GetDevice().createPipelineLayoutUnique(
402  pipeline_layout_info);
403  if (pipeline_layout.result != vk::Result::eSuccess) {
404  VALIDATION_LOG << "Could not create pipeline layout for pipeline "
405  << desc.GetLabel() << ": "
406  << vk::to_string(pipeline_layout.result);
407  return nullptr;
408  }
409  pipeline_info.setLayout(pipeline_layout.value.get());
410 
411  //----------------------------------------------------------------------------
412  /// Create the depth stencil state.
413  ///
414  auto depth_stencil_state = ToVKPipelineDepthStencilStateCreateInfo(
415  desc.GetDepthStencilAttachmentDescriptor(),
416  desc.GetFrontStencilAttachmentDescriptor(),
417  desc.GetBackStencilAttachmentDescriptor());
418  pipeline_info.setPDepthStencilState(&depth_stencil_state);
419 
420  //----------------------------------------------------------------------------
421  /// Setup the optional pipeline creation feedback struct so we can understand
422  /// how Vulkan created the PSO.
423  ///
424  auto& feedback = chain.get<vk::PipelineCreationFeedbackCreateInfoEXT>();
425  auto pipeline_feedback = EmptyFeedback();
426  std::vector<vk::PipelineCreationFeedbackEXT> stage_feedbacks(
427  pipeline_info.stageCount, EmptyFeedback());
428  feedback.setPPipelineCreationFeedback(&pipeline_feedback);
429  feedback.setPipelineStageCreationFeedbacks(stage_feedbacks);
430 
431  //----------------------------------------------------------------------------
432  /// Finally, all done with the setup info. Create the pipeline itself.
433  ///
434  auto pipeline = pso_cache->CreatePipeline(pipeline_info);
435  if (!pipeline) {
436  VALIDATION_LOG << "Could not create graphics pipeline: " << desc.GetLabel();
437  return nullptr;
438  }
439 
440  if (supports_pipeline_creation_feedback) {
441  ReportPipelineCreationFeedback(desc, feedback);
442  }
443 
444  ContextVK::SetDebugName(device_holder->GetDevice(), *pipeline_layout.value,
445  "Pipeline Layout " + desc.GetLabel());
446  ContextVK::SetDebugName(device_holder->GetDevice(), *pipeline,
447  "Pipeline " + desc.GetLabel());
448 
449  auto pipeline_vk = std::unique_ptr<PipelineVK>(new PipelineVK(
450  device_holder, //
451  library, //
452  desc, //
453  std::move(pipeline), //
454  std::move(render_pass), //
455  std::move(pipeline_layout.value), //
456  std::move(descs_layout), //
457  std::move(immutable_sampler) //
458  ));
459  if (!pipeline_vk->IsValid()) {
460  VALIDATION_LOG << "Could not create a valid pipeline.";
461  return nullptr;
462  }
463  return pipeline_vk;
464 }

References impeller::BackendCast< PipelineLibraryVK, PipelineLibrary >::Cast(), impeller::BackendCast< ShaderFunctionVK, ShaderFunction >::Cast(), impeller::CreateCompatRenderPassForPipeline(), impeller::EmptyFeedback(), impeller::PipelineDescriptor::GetBackStencilAttachmentDescriptor(), impeller::PipelineDescriptor::GetColorAttachmentDescriptors(), impeller::PipelineDescriptor::GetCullMode(), impeller::PipelineDescriptor::GetDepthStencilAttachmentDescriptor(), impeller::PipelineDescriptor::GetFrontStencilAttachmentDescriptor(), impeller::PipelineDescriptor::GetLabel(), impeller::PipelineDescriptor::GetPolygonMode(), impeller::PipelineDescriptor::GetPrimitiveType(), impeller::PipelineLibraryVK::GetPSOCache(), impeller::PipelineDescriptor::GetSampleCount(), impeller::PipelineDescriptor::GetSpecializationConstants(), impeller::PipelineDescriptor::GetStageEntrypoints(), impeller::PipelineDescriptor::GetVertexDescriptor(), impeller::PipelineDescriptor::GetWindingOrder(), impeller::kEXTPipelineCreationFeedback, impeller::kSampledImage, impeller::ReportPipelineCreationFeedback(), impeller::ContextVK::SetDebugName(), impeller::ToVertexDescriptorFormat(), impeller::ToVKCullModeFlags(), impeller::ToVKDescriptorType(), impeller::ToVKFrontFace(), impeller::ToVKPipelineColorBlendAttachmentState(), impeller::ToVKPipelineDepthStencilStateCreateInfo(), impeller::ToVKPolygonMode(), impeller::ToVKPrimitiveTopology(), impeller::ToVKSampleCountFlagBits(), impeller::ToVkShaderStage(), impeller::ToVKShaderStageFlagBits(), and VALIDATION_LOG.

Referenced by CreateVariantForImmutableSamplers().

◆ CreateVariantForImmutableSamplers()

std::shared_ptr< PipelineVK > impeller::PipelineVK::CreateVariantForImmutableSamplers ( const std::shared_ptr< SamplerVK > &  immutable_sampler) const

Definition at line 509 of file pipeline_vk.cc.

510  {
511  if (!immutable_sampler) {
512  return nullptr;
513  }
514  auto cache_key = ImmutableSamplerKeyVK{*immutable_sampler};
515  Lock lock(immutable_sampler_variants_mutex_);
516  auto found = immutable_sampler_variants_.find(cache_key);
517  if (found != immutable_sampler_variants_.end()) {
518  return found->second;
519  }
520  auto device_holder = device_holder_.lock();
521  if (!device_holder) {
522  return nullptr;
523  }
524  return (immutable_sampler_variants_[cache_key] =
525  Create(desc_, device_holder, library_, immutable_sampler));
526 }

References Create(), impeller::Pipeline< PipelineDescriptor >::desc_, and impeller::Pipeline< PipelineDescriptor >::library_.

◆ GetDescriptorSetLayout()

const vk::DescriptorSetLayout & impeller::PipelineVK::GetDescriptorSetLayout ( ) const

Definition at line 505 of file pipeline_vk.cc.

505  {
506  return *descriptor_set_layout_;
507 }

◆ GetPipeline()

vk::Pipeline impeller::PipelineVK::GetPipeline ( ) const

Definition at line 497 of file pipeline_vk.cc.

497  {
498  return *pipeline_;
499 }

◆ GetPipelineLayout()

const vk::PipelineLayout & impeller::PipelineVK::GetPipelineLayout ( ) const

Definition at line 501 of file pipeline_vk.cc.

501  {
502  return *layout_;
503 }

Friends And Related Function Documentation

◆ PipelineLibraryVK

friend class PipelineLibraryVK
friend

Definition at line 51 of file pipeline_vk.h.


The documentation for this class was generated from the following files:
impeller::CreateCompatRenderPassForPipeline
static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(const vk::Device &device, const PipelineDescriptor &desc)
Definition: pipeline_vk.cc:125
impeller::ToVKPipelineDepthStencilStateCreateInfo
vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo(std::optional< DepthAttachmentDescriptor > depth, std::optional< StencilAttachmentDescriptor > front, std::optional< StencilAttachmentDescriptor > back)
Definition: formats_vk.cc:9
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::ToVKPolygonMode
constexpr vk::PolygonMode ToVKPolygonMode(PolygonMode mode)
Definition: formats_vk.h:365
impeller::ToVKPipelineColorBlendAttachmentState
constexpr vk::PipelineColorBlendAttachmentState ToVKPipelineColorBlendAttachmentState(const ColorAttachmentDescriptor &desc)
Definition: formats_vk.h:102
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:267
impeller::PipelineVK::Create
static std::unique_ptr< PipelineVK > Create(const PipelineDescriptor &desc, const std::shared_ptr< DeviceHolderVK > &device_holder, const std::weak_ptr< PipelineLibrary > &weak_library, std::shared_ptr< SamplerVK > immutable_sampler={})
Definition: pipeline_vk.cc:167
impeller::ToVKCullModeFlags
constexpr vk::CullModeFlags ToVKCullModeFlags(CullMode mode)
Definition: formats_vk.h:419
impeller::EmptyFeedback
static vk::PipelineCreationFeedbackEXT EmptyFeedback()
Definition: pipeline_vk.cc:20
impeller::OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback
@ kEXTPipelineCreationFeedback
impeller::PipelineLibraryVK::GetPSOCache
const std::shared_ptr< PipelineCacheVK > & GetPSOCache() const
Definition: pipeline_library_vk.cc:274
impeller::ToVKPrimitiveTopology
constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive)
Definition: formats_vk.h:375
impeller::ToVertexDescriptorFormat
vk::Format ToVertexDescriptorFormat(const ShaderStageIOSlot &input)
Definition: vertex_descriptor_vk.cc:11
impeller::ToVKSampleCountFlagBits
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count)
Definition: formats_vk.h:21
impeller::ToVkShaderStage
constexpr vk::ShaderStageFlags ToVkShaderStage(ShaderStage stage)
Definition: formats_vk.h:252
impeller::ContextVK::SetDebugName
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:106
impeller::DescriptorType::kSampledImage
@ kSampledImage
impeller::Pipeline< PipelineDescriptor >::desc_
const PipelineDescriptor desc_
Definition: pipeline.h:69
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::BackendCast< PipelineLibraryVK, PipelineLibrary >::Cast
static PipelineLibraryVK & Cast(PipelineLibrary &base)
Definition: backend_cast.h:13
impeller::ToVKFrontFace
constexpr vk::FrontFace ToVKFrontFace(WindingOrder order)
Definition: pipeline_vk.cc:29
impeller::ToVKShaderStageFlagBits
constexpr std::optional< vk::ShaderStageFlagBits > ToVKShaderStageFlagBits(ShaderStage stage)
Definition: formats_vk.h:120
impeller::ReportPipelineCreationFeedback
static void ReportPipelineCreationFeedback(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:104
impeller::Pipeline< PipelineDescriptor >::library_
const std::weak_ptr< PipelineLibrary > library_
Definition: pipeline.h:67