| Flutter Impeller |

pipeline_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/pipeline_vk.h"
6
7 #include <format>
8
9 #include "flutter/fml/make_copyable.h"
10 #include "flutter/fml/status_or.h"
11 #include "flutter/fml/trace_event.h"
12 #include "impeller/base/timing.h"
13 #include "impeller/renderer/backend/vulkan/capabilities_vk.h"
14 #include "impeller/renderer/backend/vulkan/context_vk.h"
15 #include "impeller/renderer/backend/vulkan/formats_vk.h"
16 #include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
17 #include "impeller/renderer/backend/vulkan/sampler_vk.h"
18 #include "impeller/renderer/backend/vulkan/shader_function_vk.h"
19 #include "impeller/renderer/backend/vulkan/vertex_descriptor_vk.h"
20
21 namespace impeller {
22
23 static vk::PipelineCreationFeedbackEXT EmptyFeedback() {
24 vk::PipelineCreationFeedbackEXT feedback;
25 // If the VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT is not set in flags, an
26 // implementation must not set any other bits in flags, and the values of all
27 // other VkPipelineCreationFeedback data members are undefined.
28 feedback.flags = vk::PipelineCreationFeedbackFlagBits::eValid;
29 return feedback;
30 }
31
32 constexpr vk::FrontFace ToVKFrontFace(WindingOrder order) {
33 switch (order) {
34 case WindingOrder::kClockwise:
35 return vk::FrontFace::eClockwise;
36 case WindingOrder::kCounterClockwise:
37 return vk::FrontFace::eCounterClockwise;
38 }
39 FML_UNREACHABLE();
40 }
41
42 static void ReportPipelineCreationFeedbackToLog(
43 std::stringstream& stream,
44 const vk::PipelineCreationFeedbackEXT& feedback) {
45 const auto pipeline_cache_hit =
46 feedback.flags &
47 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit;
48 const auto base_pipeline_accl =
49 feedback.flags &
50 vk::PipelineCreationFeedbackFlagBits::eBasePipelineAcceleration;
51 auto duration = std::chrono::duration_cast<MillisecondsF>(
52 std::chrono::nanoseconds{feedback.duration});
53 stream << "Time: " << duration.count() << "ms"
54 << " Cache Hit: " << static_cast<bool>(pipeline_cache_hit)
55 << " Base Accel: " << static_cast<bool>(base_pipeline_accl)
56 << " Thread: " << std::this_thread::get_id();
57 }
58
59 static void ReportPipelineCreationFeedbackToLog(
60 const PipelineDescriptor& desc,
61 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
62 std::stringstream stream;
63 stream << std::fixed << std::showpoint << std::setprecision(2);
64 stream << std::endl << ">>>>>>" << std::endl;
65 stream << "Pipeline '" << desc.GetLabel() << "' ";
66 ReportPipelineCreationFeedbackToLog(stream,
67 *feedback.pPipelineCreationFeedback);
68 if (feedback.pipelineStageCreationFeedbackCount != 0) {
69 stream << std::endl;
70 }
71 for (size_t i = 0, count = feedback.pipelineStageCreationFeedbackCount;
72 i < count; i++) {
73 stream << "\tStage " << i + 1 << ": ";
74 ReportPipelineCreationFeedbackToLog(
75 stream, feedback.pPipelineStageCreationFeedbacks[i]);
76 if (i != count - 1) {
77 stream << std::endl;
78 }
79 }
80 stream << std::endl << "<<<<<<" << std::endl;
81 FML_LOG(ERROR) << stream.str();
82 }
83
84 static void ReportPipelineCreationFeedbackToTrace(
85 const PipelineDescriptor& desc,
86 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
87 static int64_t gPipelineCacheHits = 0;
88 static int64_t gPipelineCacheMisses = 0;
89 static int64_t gPipelines = 0;
90 if (feedback.pPipelineCreationFeedback->flags &
91 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit) {
92 gPipelineCacheHits++;
93 } else {
94 gPipelineCacheMisses++;
95 }
96 gPipelines++;
97 static constexpr int64_t kImpellerPipelineTraceID = 1988;
98 FML_TRACE_COUNTER("impeller", //
99 "PipelineCache", // series name
100 kImpellerPipelineTraceID, // series ID
101 "PipelineCacheHits", gPipelineCacheHits, //
102 "PipelineCacheMisses", gPipelineCacheMisses, //
103 "TotalPipelines", gPipelines //
104 );
105 }
106
107 static void ReportPipelineCreationFeedback(
108 const PipelineDescriptor& desc,
109 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
110 constexpr bool kReportPipelineCreationFeedbackToLogs = false;
111 constexpr bool kReportPipelineCreationFeedbackToTraces = true;
112 if (kReportPipelineCreationFeedbackToLogs) {
113 ReportPipelineCreationFeedbackToLog(desc, feedback);
114 }
115 if (kReportPipelineCreationFeedbackToTraces) {
116 ReportPipelineCreationFeedbackToTrace(desc, feedback);
117 }
118 }
119
120 //----------------------------------------------------------------------------
121 /// Render Pass
122 /// We are NOT going to use the same render pass with the framebuffer (later)
123 /// and the graphics pipeline (here). Instead, we are going to ensure that the
124 /// sub-passes are compatible. To see the compatibility rules, see the Vulkan
125 /// spec:
126 /// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/chap8.html#renderpass-compatibility
127 ///
128 static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(
129 const vk::Device& device,
130 const PipelineDescriptor& desc) {
131 RenderPassBuilderVK builder;
132
133 for (const auto& [bind_point, color] : desc.GetColorAttachmentDescriptors()) {
134 builder.SetColorAttachment(bind_point, //
135 color.format, //
136 desc.GetSampleCount(), //
137 LoadAction::kDontCare, //
138 StoreAction::kDontCare //
139 );
140 }
141
142 if (auto depth = desc.GetDepthStencilAttachmentDescriptor();
143 depth.has_value()) {
144 builder.SetDepthStencilAttachment(desc.GetDepthPixelFormat(), //
145 desc.GetSampleCount(), //
146 LoadAction::kDontCare, //
147 StoreAction::kDontCare //
148 );
149 } else if (desc.HasStencilAttachmentDescriptors()) {
150 builder.SetStencilAttachment(desc.GetStencilPixelFormat(), //
151 desc.GetSampleCount(), //
152 LoadAction::kDontCare, //
153 StoreAction::kDontCare //
154 );
155 }
156
157 auto pass = builder.Build(device);
158 if (!pass) {
159 VALIDATION_LOG << "Failed to create render pass for pipeline: "
160 << desc.GetLabel();
161 return {};
162 }
163
164 #ifdef IMPELLER_DEBUG
165 ContextVK::SetDebugName(
166 device, pass.get(),
167 std::format("Compat Render Pass: {}", desc.GetLabel()));
168 #endif // IMPELLER_DEBUG
169
170 return pass;
171 }
172
173 namespace {
174 fml::StatusOr<vk::UniqueDescriptorSetLayout> MakeDescriptorSetLayout(
175 const PipelineDescriptor& desc,
176 const std::shared_ptr<DeviceHolderVK>& device_holder,
177 const std::shared_ptr<SamplerVK>& immutable_sampler) {
178 std::vector<vk::DescriptorSetLayoutBinding> set_bindings;
179
180 vk::Sampler vk_immutable_sampler =
181 immutable_sampler ? immutable_sampler->GetSampler()
182 : static_cast<vk::Sampler>(VK_NULL_HANDLE);
183
184 for (auto layout : desc.GetVertexDescriptor()->GetDescriptorSetLayouts()) {
185 vk::DescriptorSetLayoutBinding set_binding;
186 set_binding.binding = layout.binding;
187 set_binding.descriptorCount = 1u;
188 set_binding.descriptorType = ToVKDescriptorType(layout.descriptor_type);
189 set_binding.stageFlags = ToVkShaderStage(layout.shader_stage);
190 // TODO(143719): This specifies the immutable sampler for all sampled
191 // images. This is incorrect. In cases where the shader samples from the
192 // multiple images, there is currently no way to tell which sampler needs to
193 // be immutable and which one needs a binding set in the render pass. Expect
194 // errors if the shader has more than on sampled image. The sampling from
195 // the one that is expected to be non-immutable will be incorrect.
196 if (vk_immutable_sampler &&
197 layout.descriptor_type == DescriptorType::kSampledImage) {
198 set_binding.setImmutableSamplers(vk_immutable_sampler);
199 }
200 set_bindings.push_back(set_binding);
201 }
202
203 vk::DescriptorSetLayoutCreateInfo desc_set_layout_info;
204 desc_set_layout_info.setBindings(set_bindings);
205
206 auto [descs_result, descs_layout] =
207 device_holder->GetDevice().createDescriptorSetLayoutUnique(
208 desc_set_layout_info);
209 if (descs_result != vk::Result::eSuccess) {
210 VALIDATION_LOG << "unable to create uniform descriptors";
211 return {fml::Status(fml::StatusCode::kUnknown,
212 "unable to create uniform descriptors")};
213 }
214
215 #ifdef IMPELLER_DEBUG
216 ContextVK::SetDebugName(
217 device_holder->GetDevice(), descs_layout.get(),
218 std::format("Descriptor Set Layout: {}", desc.GetLabel()));
219 #endif // IMPELLER_DEBUG
220
221 return fml::StatusOr<vk::UniqueDescriptorSetLayout>(std::move(descs_layout));
222 }
223
224 fml::StatusOr<vk::UniquePipelineLayout> MakePipelineLayout(
225 const PipelineDescriptor& desc,
226 const std::shared_ptr<DeviceHolderVK>& device_holder,
227 const vk::DescriptorSetLayout& descs_layout) {
228 vk::PipelineLayoutCreateInfo pipeline_layout_info;
229 pipeline_layout_info.setSetLayouts(descs_layout);
230 auto pipeline_layout = device_holder->GetDevice().createPipelineLayoutUnique(
231 pipeline_layout_info);
232 if (pipeline_layout.result != vk::Result::eSuccess) {
233 VALIDATION_LOG << "Could not create pipeline layout for pipeline "
234 << desc.GetLabel() << ": "
235 << vk::to_string(pipeline_layout.result);
236 return {fml::Status(fml::StatusCode::kUnknown,
237 "Could not create pipeline layout for pipeline.")};
238 }
239
240 #ifdef IMPELLER_DEBUG
241 ContextVK::SetDebugName(device_holder->GetDevice(), *pipeline_layout.value,
242 std::format("Pipeline Layout {}", desc.GetLabel()));
243 #endif // IMPELLER_DEBUG
244
245 return std::move(pipeline_layout.value);
246 }
247
248 fml::StatusOr<vk::UniquePipeline> MakePipeline(
249 const PipelineDescriptor& desc,
250 const std::shared_ptr<DeviceHolderVK>& device_holder,
251 const std::shared_ptr<PipelineCacheVK>& pso_cache,
252 const vk::PipelineLayout& pipeline_layout,
253 const vk::RenderPass& render_pass) {
254 vk::StructureChain<vk::GraphicsPipelineCreateInfo,
255 vk::PipelineCreationFeedbackCreateInfoEXT>
256 chain;
257
258 const auto* caps = pso_cache->GetCapabilities();
259
260 const auto supports_pipeline_creation_feedback = caps->HasExtension(
261 OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback);
262 if (!supports_pipeline_creation_feedback) {
263 chain.unlink<vk::PipelineCreationFeedbackCreateInfoEXT>();
264 }
265
266 auto& pipeline_info = chain.get<vk::GraphicsPipelineCreateInfo>();
267 pipeline_info.setLayout(pipeline_layout);
268
269 //----------------------------------------------------------------------------
270 /// Dynamic States
271 ///
272 vk::PipelineDynamicStateCreateInfo dynamic_create_state_info;
273 std::vector<vk::DynamicState> dynamic_states = {
274 vk::DynamicState::eViewport,
275 vk::DynamicState::eScissor,
276 vk::DynamicState::eStencilReference,
277 };
278 dynamic_create_state_info.setDynamicStates(dynamic_states);
279 pipeline_info.setPDynamicState(&dynamic_create_state_info);
280
281 //----------------------------------------------------------------------------
282 /// Viewport State
283 ///
284 vk::PipelineViewportStateCreateInfo viewport_state;
285 viewport_state.setViewportCount(1u);
286 viewport_state.setScissorCount(1u);
287 // The actual viewport and scissor rects are not set here since they are
288 // dynamic as mentioned above in the dynamic state info.
289 pipeline_info.setPViewportState(&viewport_state);
290
291 //----------------------------------------------------------------------------
292 /// Shader Stages
293 ///
294 const auto& constants = desc.GetSpecializationConstants();
295
296 std::vector<std::vector<vk::SpecializationMapEntry>> map_entries(
297 desc.GetStageEntrypoints().size());
298 std::vector<vk::SpecializationInfo> specialization_infos(
299 desc.GetStageEntrypoints().size());
300 std::vector<vk::PipelineShaderStageCreateInfo> shader_stages;
301
302 size_t entrypoint_count = 0;
303 for (const auto& entrypoint : desc.GetStageEntrypoints()) {
304 auto stage = ToVKShaderStageFlagBits(entrypoint.first);
305 if (!stage.has_value()) {
306 VALIDATION_LOG << "Unsupported shader type in pipeline: "
307 << desc.GetLabel();
308 return {fml::Status(fml::StatusCode::kUnknown,
309 "Unsupported shader type in pipeline.")};
310 }
311
312 std::vector<vk::SpecializationMapEntry>& entries =
313 map_entries[entrypoint_count];
314 for (auto i = 0u; i < constants.size(); i++) {
315 vk::SpecializationMapEntry entry;
316 entry.offset = (i * sizeof(Scalar));
317 entry.size = sizeof(Scalar);
318 entry.constantID = i;
319 entries.emplace_back(entry);
320 }
321
322 vk::SpecializationInfo& specialization_info =
323 specialization_infos[entrypoint_count];
324 specialization_info.setMapEntries(map_entries[entrypoint_count]);
325 specialization_info.setPData(constants.data());
326 specialization_info.setDataSize(sizeof(Scalar) * constants.size());
327
328 vk::PipelineShaderStageCreateInfo info;
329 info.setStage(stage.value());
330 info.setPName("main");
331 info.setModule(
332 ShaderFunctionVK::Cast(entrypoint.second.get())->GetModule());
333 info.setPSpecializationInfo(&specialization_info);
334 shader_stages.push_back(info);
335 entrypoint_count++;
336 }
337 pipeline_info.setStages(shader_stages);
338
339 //----------------------------------------------------------------------------
340 /// Rasterization State
341 ///
342 vk::PipelineRasterizationStateCreateInfo rasterization_state;
343 rasterization_state.setFrontFace(ToVKFrontFace(desc.GetWindingOrder()));
344 rasterization_state.setCullMode(ToVKCullModeFlags(desc.GetCullMode()));
345 rasterization_state.setPolygonMode(ToVKPolygonMode(desc.GetPolygonMode()));
346 rasterization_state.setLineWidth(1.0f);
347 rasterization_state.setDepthClampEnable(false);
348 rasterization_state.setRasterizerDiscardEnable(false);
349 pipeline_info.setPRasterizationState(&rasterization_state);
350
351 //----------------------------------------------------------------------------
352 /// Multi-sample State
353 ///
354 vk::PipelineMultisampleStateCreateInfo multisample_state;
355 multisample_state.setRasterizationSamples(
356 ToVKSampleCountFlagBits(desc.GetSampleCount()));
357 pipeline_info.setPMultisampleState(&multisample_state);
358
359 //----------------------------------------------------------------------------
360 /// Primitive Input Assembly State
361 vk::PipelineInputAssemblyStateCreateInfo input_assembly;
362 const auto topology = ToVKPrimitiveTopology(desc.GetPrimitiveType());
363 input_assembly.setTopology(topology);
364 input_assembly.setPrimitiveRestartEnable(
365 caps->SupportsPrimitiveRestart() &&
366 PrimitiveTopologySupportsPrimitiveRestart(desc.GetPrimitiveType()));
367 pipeline_info.setPInputAssemblyState(&input_assembly);
368
369 //----------------------------------------------------------------------------
370 /// Color Blend State
371 std::vector<vk::PipelineColorBlendAttachmentState> attachment_blend_state;
372 for (const auto& color_desc : desc.GetColorAttachmentDescriptors()) {
373 // TODO(csg): The blend states are per color attachment. But it isn't clear
374 // how the color attachment indices are specified in the pipeline create
375 // info. But, this should always work for one color attachment.
376 attachment_blend_state.push_back(
377 ToVKPipelineColorBlendAttachmentState(color_desc.second));
378 }
379 vk::PipelineColorBlendStateCreateInfo blend_state;
380 blend_state.setAttachments(attachment_blend_state);
381 pipeline_info.setPColorBlendState(&blend_state);
382
383 // Convention wisdom says that the base acceleration pipelines are never used
384 // by drivers for cache hits. Instead, the PSO cache is the preferred
385 // mechanism.
386 pipeline_info.setBasePipelineHandle(VK_NULL_HANDLE);
387 pipeline_info.setSubpass(0u);
388 pipeline_info.setRenderPass(render_pass);
389
390 //----------------------------------------------------------------------------
391 /// Vertex Input Setup
392 ///
393 std::vector<vk::VertexInputAttributeDescription> attr_descs;
394 std::vector<vk::VertexInputBindingDescription> buffer_descs;
395
396 const auto& stage_inputs = desc.GetVertexDescriptor()->GetStageInputs();
397 const auto& stage_buffer_layouts =
398 desc.GetVertexDescriptor()->GetStageLayouts();
399 for (const ShaderStageIOSlot& stage_in : stage_inputs) {
400 vk::VertexInputAttributeDescription attr_desc;
401 attr_desc.setBinding(stage_in.binding);
402 attr_desc.setLocation(stage_in.location);
403 attr_desc.setFormat(ToVertexDescriptorFormat(stage_in));
404 attr_desc.setOffset(stage_in.offset);
405 attr_descs.push_back(attr_desc);
406 }
407 for (const ShaderStageBufferLayout& layout : stage_buffer_layouts) {
408 vk::VertexInputBindingDescription binding_description;
409 binding_description.setBinding(layout.binding);
410 binding_description.setInputRate(vk::VertexInputRate::eVertex);
411 binding_description.setStride(layout.stride);
412 buffer_descs.push_back(binding_description);
413 }
414
415 vk::PipelineVertexInputStateCreateInfo vertex_input_state;
416 vertex_input_state.setVertexAttributeDescriptions(attr_descs);
417 vertex_input_state.setVertexBindingDescriptions(buffer_descs);
418
419 pipeline_info.setPVertexInputState(&vertex_input_state);
420
421 //----------------------------------------------------------------------------
422 /// Create the depth stencil state.
423 ///
424 auto depth_stencil_state = ToVKPipelineDepthStencilStateCreateInfo(
425 desc.GetDepthStencilAttachmentDescriptor(),
426 desc.GetFrontStencilAttachmentDescriptor(),
427 desc.GetBackStencilAttachmentDescriptor());
428 pipeline_info.setPDepthStencilState(&depth_stencil_state);
429
430 //----------------------------------------------------------------------------
431 /// Setup the optional pipeline creation feedback struct so we can understand
432 /// how Vulkan created the PSO.
433 ///
434 auto& feedback = chain.get<vk::PipelineCreationFeedbackCreateInfoEXT>();
435 auto pipeline_feedback = EmptyFeedback();
436 std::vector<vk::PipelineCreationFeedbackEXT> stage_feedbacks(
437 pipeline_info.stageCount, EmptyFeedback());
438 feedback.setPPipelineCreationFeedback(&pipeline_feedback);
439 feedback.setPipelineStageCreationFeedbacks(stage_feedbacks);
440
441 //----------------------------------------------------------------------------
442 /// Finally, all done with the setup info. Create the pipeline itself.
443 ///
444 auto pipeline = pso_cache->CreatePipeline(pipeline_info);
445 if (!pipeline) {
446 VALIDATION_LOG << "Could not create graphics pipeline: " << desc.GetLabel();
447 return {fml::Status(fml::StatusCode::kUnknown,
448 "Could not create graphics pipeline.")};
449 }
450
451 if (supports_pipeline_creation_feedback) {
452 ReportPipelineCreationFeedback(desc, feedback);
453 }
454
455 #ifdef IMPELLER_DEBUG
456 ContextVK::SetDebugName(device_holder->GetDevice(), *pipeline,
457 std::format("Pipeline {}", desc.GetLabel()));
458 #endif // IMPELLER_DEBUG
459
460 return std::move(pipeline);
461 }
462 } // namespace
463
464 std::unique_ptr<PipelineVK> PipelineVK::Create(
465 const PipelineDescriptor& desc,
466 const std::shared_ptr<DeviceHolderVK>& device_holder,
467 const std::weak_ptr<PipelineLibrary>& weak_library,
468 PipelineKey pipeline_key,
469 std::shared_ptr<SamplerVK> immutable_sampler) {
470 TRACE_EVENT1("flutter", "PipelineVK::Create", "Name", desc.GetLabel().data());
471
472 auto library = weak_library.lock();
473
474 if (!device_holder || !library) {
475 return nullptr;
476 }
477
478 const auto& pso_cache = PipelineLibraryVK::Cast(*library).GetPSOCache();
479
480 fml::StatusOr<vk::UniqueDescriptorSetLayout> descs_layout =
481 MakeDescriptorSetLayout(desc, device_holder, immutable_sampler);
482 if (!descs_layout.ok()) {
483 return nullptr;
484 }
485
486 fml::StatusOr<vk::UniquePipelineLayout> pipeline_layout =
487 MakePipelineLayout(desc, device_holder, descs_layout.value().get());
488 if (!pipeline_layout.ok()) {
489 return nullptr;
490 }
491
492 vk::UniqueRenderPass render_pass =
493 CreateCompatRenderPassForPipeline(device_holder->GetDevice(), desc);
494 if (!render_pass) {
495 VALIDATION_LOG << "Could not create render pass for pipeline.";
496 return nullptr;
497 }
498
499 fml::StatusOr<vk::UniquePipeline> pipeline =
500 MakePipeline(desc, device_holder, pso_cache,
501 pipeline_layout.value().get(), render_pass.get());
502 if (!pipeline.ok()) {
503 return nullptr;
504 }
505
506 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
507 auto pipeline_vk = std::unique_ptr<PipelineVK>(new PipelineVK(
508 device_holder, //
509 library, //
510 desc, //
511 std::move(pipeline.value()), //
512 std::move(render_pass), //
513 std::move(pipeline_layout.value()), //
514 std::move(descs_layout.value()), //
515 pipeline_key, //
516 std::move(immutable_sampler) //
517 ));
518 if (!pipeline_vk->IsValid()) {
519 VALIDATION_LOG << "Could not create a valid pipeline.";
520 return nullptr;
521 }
522 return pipeline_vk;
523 }
524
525 PipelineVK::PipelineVK(std::weak_ptr<DeviceHolderVK> device_holder,
526 std::weak_ptr<PipelineLibrary> library,
527 const PipelineDescriptor& desc,
528 vk::UniquePipeline pipeline,
529 vk::UniqueRenderPass render_pass,
530 vk::UniquePipelineLayout layout,
531 vk::UniqueDescriptorSetLayout descriptor_set_layout,
532 PipelineKey pipeline_key,
533 std::shared_ptr<SamplerVK> immutable_sampler)
534 : Pipeline(std::move(library), desc),
535 device_holder_(std::move(device_holder)),
536 pipeline_(std::move(pipeline)),
537 render_pass_(std::move(render_pass)),
538 layout_(std::move(layout)),
539 descriptor_set_layout_(std::move(descriptor_set_layout)),
540 immutable_sampler_(std::move(immutable_sampler)),
541 pipeline_key_(pipeline_key) {
542 is_valid_ = pipeline_ && render_pass_ && layout_ && descriptor_set_layout_;
543 }
544
545 PipelineVK::~PipelineVK() {
546 if (auto device = device_holder_.lock(); !device) {
547 descriptor_set_layout_.release();
548 layout_.release();
549 render_pass_.release();
550 pipeline_.release();
551 }
552 }
553
554 bool PipelineVK::IsValid() const {
555 return is_valid_;
556 }
557
558 vk::Pipeline PipelineVK::GetPipeline() const {
559 return *pipeline_;
560 }
561
562 const vk::PipelineLayout& PipelineVK::GetPipelineLayout() const {
563 return *layout_;
564 }
565
566 const vk::DescriptorSetLayout& PipelineVK::GetDescriptorSetLayout() const {
567 return *descriptor_set_layout_;
568 }
569
570 std::shared_ptr<PipelineVK> PipelineVK::CreateVariantForImmutableSamplers(
571 const std::shared_ptr<SamplerVK>& immutable_sampler) const {
572 if (!immutable_sampler) {
573 return nullptr;
574 }
575 auto cache_key = ImmutableSamplerKeyVK{*immutable_sampler};
576 Lock lock(immutable_sampler_variants_mutex_);
577 auto found = immutable_sampler_variants_.find(cache_key);
578 if (found != immutable_sampler_variants_.end()) {
579 return found->second;
580 }
581 auto device_holder = device_holder_.lock();
582 if (!device_holder) {
583 return nullptr;
584 }
585 // Note: immutable sampler variant of a pipeline is the negation of the
586 // existing pipeline key. This keeps the descriptors separate.
587 return (immutable_sampler_variants_[cache_key] =
588 Create(desc_, device_holder, library_, -1 * pipeline_key_,
589 immutable_sampler));
590 }
591
592 } // namespace impeller
capabilities_vk.h
impeller::BackendCast< ShaderFunctionVK, ShaderFunction >::Cast
static ShaderFunctionVK & Cast(ShaderFunction &base)
Definition: backend_cast.h:13
impeller::ContextVK::SetDebugName
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:151
impeller::Lock
Definition: thread.h:72
impeller::PipelineDescriptor
Definition: pipeline_descriptor.h:24
impeller::PipelineDescriptor::GetLabel
std::string_view GetLabel() const
Definition: pipeline_descriptor.cc:234
impeller::PipelineDescriptor::GetDepthPixelFormat
PixelFormat GetDepthPixelFormat() const
Definition: pipeline_descriptor.cc:238
impeller::PipelineDescriptor::GetDepthStencilAttachmentDescriptor
std::optional< DepthAttachmentDescriptor > GetDepthStencilAttachmentDescriptor() const
Definition: pipeline_descriptor.cc:207
impeller::PipelineDescriptor::GetStencilPixelFormat
PixelFormat GetStencilPixelFormat() const
Definition: pipeline_descriptor.cc:197
impeller::PipelineDescriptor::GetColorAttachmentDescriptors
const std::map< size_t, ColorAttachmentDescriptor > & GetColorAttachmentDescriptors() const
Definition: pipeline_descriptor.cc:212
impeller::PipelineDescriptor::HasStencilAttachmentDescriptors
bool HasStencilAttachmentDescriptors() const
Definition: pipeline_descriptor.cc:247
impeller::PipelineDescriptor::GetSampleCount
SampleCount GetSampleCount() const
Definition: pipeline_descriptor.h:36
impeller::Pipeline
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition: pipeline.h:52
impeller::Pipeline< PipelineDescriptor >::library_
const std::weak_ptr< PipelineLibrary > library_
Definition: pipeline.h:72
impeller::Pipeline< PipelineDescriptor >::desc_
const PipelineDescriptor desc_
Definition: pipeline.h:74
impeller::PipelineLibraryVK::GetPSOCache
const std::shared_ptr< PipelineCacheVK > & GetPSOCache() const
Definition: pipeline_library_vk.cc:298
impeller::PipelineVK
Definition: pipeline_vk.h:27
impeller::PipelineVK::CreateVariantForImmutableSamplers
std::shared_ptr< PipelineVK > CreateVariantForImmutableSamplers(const std::shared_ptr< SamplerVK > &immutable_sampler) const
Definition: pipeline_vk.cc:570
impeller::PipelineVK::~PipelineVK
~PipelineVK() override
Definition: pipeline_vk.cc:545
impeller::PipelineVK::GetPipelineLayout
const vk::PipelineLayout & GetPipelineLayout() const
Definition: pipeline_vk.cc:562
impeller::PipelineVK::GetDescriptorSetLayout
const vk::DescriptorSetLayout & GetDescriptorSetLayout() const
Definition: pipeline_vk.cc:566
impeller::PipelineVK::GetPipeline
vk::Pipeline GetPipeline() const
Definition: pipeline_vk.cc:558
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, PipelineKey pipeline_key, std::shared_ptr< SamplerVK > immutable_sampler={})
Definition: pipeline_vk.cc:464
impeller::RenderPassBuilderVK
Definition: render_pass_builder_vk.h:21
impeller::RenderPassBuilderVK::SetDepthStencilAttachment
RenderPassBuilderVK & SetDepthStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
Definition: render_pass_builder_vk.cc:86
impeller::RenderPassBuilderVK::SetStencilAttachment
RenderPassBuilderVK & SetStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
Definition: render_pass_builder_vk.cc:104
impeller::RenderPassBuilderVK::SetColorAttachment
RenderPassBuilderVK & SetColorAttachment(size_t index, PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action, vk::ImageLayout current_layout=vk::ImageLayout::eUndefined, bool is_swapchain=false)
Definition: render_pass_builder_vk.cc:38
impeller::RenderPassBuilderVK::Build
vk::UniqueRenderPass Build(const vk::Device &device) const
Definition: render_pass_builder_vk.cc:122
formats_vk.h
impeller
Definition: allocation.cc:12
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::ToVertexDescriptorFormat
vk::Format ToVertexDescriptorFormat(const ShaderStageIOSlot &input)
Definition: vertex_descriptor_vk.cc:11
impeller::ReportPipelineCreationFeedback
static void ReportPipelineCreationFeedback(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:107
impeller::ToVKPipelineColorBlendAttachmentState
constexpr vk::PipelineColorBlendAttachmentState ToVKPipelineColorBlendAttachmentState(const ColorAttachmentDescriptor &desc)
Definition: formats_vk.h:113
impeller::EmptyFeedback
static vk::PipelineCreationFeedbackEXT EmptyFeedback()
Definition: pipeline_vk.cc:23
impeller::PipelineKey
int64_t PipelineKey
Definition: pipeline.h:21
impeller::ToVKSampleCountFlagBits
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count)
Definition: formats_vk.h:32
impeller::ToVKShaderStageFlagBits
constexpr std::optional< vk::ShaderStageFlagBits > ToVKShaderStageFlagBits(ShaderStage stage)
Definition: formats_vk.h:131
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:294
impeller::ToVKPolygonMode
constexpr vk::PolygonMode ToVKPolygonMode(PolygonMode mode)
Definition: formats_vk.h:372
impeller::ToVKCullModeFlags
constexpr vk::CullModeFlags ToVKCullModeFlags(CullMode mode)
Definition: formats_vk.h:444
impeller::ReportPipelineCreationFeedbackToLog
static void ReportPipelineCreationFeedbackToLog(std::stringstream &stream, const vk::PipelineCreationFeedbackEXT &feedback)
Definition: pipeline_vk.cc:42
impeller::ToVKPipelineDepthStencilStateCreateInfo
vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo(std::optional< DepthAttachmentDescriptor > depth, std::optional< StencilAttachmentDescriptor > front, std::optional< StencilAttachmentDescriptor > back)
Definition: formats_vk.cc:9
impeller::PrimitiveTopologySupportsPrimitiveRestart
constexpr bool PrimitiveTopologySupportsPrimitiveRestart(PrimitiveType primitive)
Definition: formats_vk.h:382
impeller::WindingOrder
WindingOrder
Definition: formats.h:22
impeller::WindingOrder::kClockwise
@ kClockwise
impeller::WindingOrder::kCounterClockwise
@ kCounterClockwise
impeller::ToVKFrontFace
constexpr vk::FrontFace ToVKFrontFace(WindingOrder order)
Definition: pipeline_vk.cc:32
impeller::LoadAction::kDontCare
@ kDontCare
impeller::StoreAction::kDontCare
@ kDontCare
impeller::ToVkShaderStage
constexpr vk::ShaderStageFlags ToVkShaderStage(ShaderStage stage)
Definition: formats_vk.h:266
impeller::ToVKPrimitiveTopology
constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive)
Definition: formats_vk.h:397
impeller::ReportPipelineCreationFeedbackToTrace
static void ReportPipelineCreationFeedbackToTrace(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:84
impeller::CreateCompatRenderPassForPipeline
static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(const vk::Device &device, const PipelineDescriptor &desc)
Definition: pipeline_vk.cc:128
impeller::DescriptorType::kSampledImage
@ kSampledImage
impeller::OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback
@ kEXTPipelineCreationFeedback
std
Definition: comparable.h:95
pipeline_vk.h
render_pass_builder_vk.h
context_vk.h
sampler_vk.h
shader_function_vk.h
impeller::ImmutableSamplerKeyVK
Definition: yuv_conversion_vk.h:94
timing.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91
vertex_descriptor_vk.h