| Flutter Impeller |

Public Member Functions | Static Public Member Functions | Friends | List of all members
impeller::PipelineVK Class Referencefinal

`#include <pipeline_vk.h>`

Inheritance diagram for impeller::PipelineVK:

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

## Static Public Member Functions
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={})
Static Public Member Functions inherited from impeller::BackendCast< PipelineVK, Pipeline< PipelineDescriptor > >
static PipelineVK & | Cast (Pipeline< PipelineDescriptor > &base)
static const PipelineVK & | Cast (const Pipeline< PipelineDescriptor > &base)
static PipelineVK * | Cast (Pipeline< PipelineDescriptor > *base)
static const PipelineVK * | Cast (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< PipelineLibrary > | library_
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(
189 OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback);
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/renderer/backend/vulkan/pipeline_vk.h
- impeller/renderer/backend/vulkan/pipeline_vk.cc

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