| 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 "flutter/fml/make_copyable.h"
8 #include "flutter/fml/status_or.h"
9 #include "flutter/fml/trace_event.h"
10 #include "impeller/base/strings.h"
11 #include "impeller/base/timing.h"
12 #include "impeller/renderer/backend/vulkan/capabilities_vk.h"
13 #include "impeller/renderer/backend/vulkan/context_vk.h"
14 #include "impeller/renderer/backend/vulkan/formats_vk.h"
15 #include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
16 #include "impeller/renderer/backend/vulkan/sampler_vk.h"
17 #include "impeller/renderer/backend/vulkan/shader_function_vk.h"
18 #include "impeller/renderer/backend/vulkan/vertex_descriptor_vk.h"
19
20 namespace impeller {
21
22 static vk::PipelineCreationFeedbackEXT EmptyFeedback() {
23 vk::PipelineCreationFeedbackEXT feedback;
24 // If the VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT is not set in flags, an
25 // implementation must not set any other bits in flags, and the values of all
26 // other VkPipelineCreationFeedback data members are undefined.
27 feedback.flags = vk::PipelineCreationFeedbackFlagBits::eValid;
28 return feedback;
29 }
30
31 constexpr vk::FrontFace ToVKFrontFace(WindingOrder order) {
32 switch (order) {
33 case WindingOrder::kClockwise:
34 return vk::FrontFace::eClockwise;
35 case WindingOrder::kCounterClockwise:
36 return vk::FrontFace::eCounterClockwise;
37 }
38 FML_UNREACHABLE();
39 }
40
41 static void ReportPipelineCreationFeedbackToLog(
42 std::stringstream& stream,
43 const vk::PipelineCreationFeedbackEXT& feedback) {
44 const auto pipeline_cache_hit =
45 feedback.flags &
46 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit;
47 const auto base_pipeline_accl =
48 feedback.flags &
49 vk::PipelineCreationFeedbackFlagBits::eBasePipelineAcceleration;
50 auto duration = std::chrono::duration_cast<MillisecondsF>(
51 std::chrono::nanoseconds{feedback.duration});
52 stream << "Time: " << duration.count() << "ms"
53 << " Cache Hit: " << static_cast<bool>(pipeline_cache_hit)
54 << " Base Accel: " << static_cast<bool>(base_pipeline_accl)
55 << " Thread: " << std::this_thread::get_id();
56 }
57
58 static void ReportPipelineCreationFeedbackToLog(
59 const PipelineDescriptor& desc,
60 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
61 std::stringstream stream;
62 stream << std::fixed << std::showpoint << std::setprecision(2);
63 stream << std::endl << ">>>>>>" << std::endl;
64 stream << "Pipeline '" << desc.GetLabel() << "' ";
65 ReportPipelineCreationFeedbackToLog(stream,
66 *feedback.pPipelineCreationFeedback);
67 if (feedback.pipelineStageCreationFeedbackCount != 0) {
68 stream << std::endl;
69 }
70 for (size_t i = 0, count = feedback.pipelineStageCreationFeedbackCount;
71 i < count; i++) {
72 stream << "\tStage " << i + 1 << ": ";
73 ReportPipelineCreationFeedbackToLog(
74 stream, feedback.pPipelineStageCreationFeedbacks[i]);
75 if (i != count - 1) {
76 stream << std::endl;
77 }
78 }
79 stream << std::endl << "<<<<<<" << std::endl;
80 FML_LOG(ERROR) << stream.str();
81 }
82
83 static void ReportPipelineCreationFeedbackToTrace(
84 const PipelineDescriptor& desc,
85 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
86 static int64_t gPipelineCacheHits = 0;
87 static int64_t gPipelineCacheMisses = 0;
88 static int64_t gPipelines = 0;
89 if (feedback.pPipelineCreationFeedback->flags &
90 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit) {
91 gPipelineCacheHits++;
92 } else {
93 gPipelineCacheMisses++;
94 }
95 gPipelines++;
96 static constexpr int64_t kImpellerPipelineTraceID = 1988;
97 FML_TRACE_COUNTER("impeller", //
98 "PipelineCache", // series name
99 kImpellerPipelineTraceID, // series ID
100 "PipelineCacheHits", gPipelineCacheHits, //
101 "PipelineCacheMisses", gPipelineCacheMisses, //
102 "TotalPipelines", gPipelines //
103 );
104 }
105
106 static void ReportPipelineCreationFeedback(
107 const PipelineDescriptor& desc,
108 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
109 constexpr bool kReportPipelineCreationFeedbackToLogs = false;
110 constexpr bool kReportPipelineCreationFeedbackToTraces = true;
111 if (kReportPipelineCreationFeedbackToLogs) {
112 ReportPipelineCreationFeedbackToLog(desc, feedback);
113 }
114 if (kReportPipelineCreationFeedbackToTraces) {
115 ReportPipelineCreationFeedbackToTrace(desc, feedback);
116 }
117 }
118
119 //----------------------------------------------------------------------------
120 /// Render Pass
121 /// We are NOT going to use the same render pass with the framebuffer (later)
122 /// and the graphics pipeline (here). Instead, we are going to ensure that the
123 /// sub-passes are compatible. To see the compatibility rules, see the Vulkan
124 /// spec:
125 /// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/chap8.html#renderpass-compatibility
126 ///
127 static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(
128 const vk::Device& device,
129 const PipelineDescriptor& desc) {
130 RenderPassBuilderVK builder;
131
132 for (const auto& [bind_point, color] : desc.GetColorAttachmentDescriptors()) {
133 builder.SetColorAttachment(bind_point, //
134 color.format, //
135 desc.GetSampleCount(), //
136 LoadAction::kDontCare, //
137 StoreAction::kDontCare //
138 );
139 }
140
141 if (auto depth = desc.GetDepthStencilAttachmentDescriptor();
142 depth.has_value()) {
143 builder.SetDepthStencilAttachment(desc.GetDepthPixelFormat(), //
144 desc.GetSampleCount(), //
145 LoadAction::kDontCare, //
146 StoreAction::kDontCare //
147 );
148 } else if (desc.HasStencilAttachmentDescriptors()) {
149 builder.SetStencilAttachment(desc.GetStencilPixelFormat(), //
150 desc.GetSampleCount(), //
151 LoadAction::kDontCare, //
152 StoreAction::kDontCare //
153 );
154 }
155
156 auto pass = builder.Build(device);
157 if (!pass) {
158 VALIDATION_LOG << "Failed to create render pass for pipeline: "
159 << desc.GetLabel();
160 return {};
161 }
162
163 #ifdef IMPELLER_DEBUG
164 ContextVK::SetDebugName(
165 device, pass.get(),
166 SPrintF("Compat Render Pass: %s", desc.GetLabel().data()));
167 #endif // IMPELLER_DEBUG
168
169 return pass;
170 }
171
172 namespace {
173 fml::StatusOr<vk::UniqueDescriptorSetLayout> MakeDescriptorSetLayout(
174 const PipelineDescriptor& desc,
175 const std::shared_ptr<DeviceHolderVK>& device_holder,
176 const std::shared_ptr<SamplerVK>& immutable_sampler) {
177 std::vector<vk::DescriptorSetLayoutBinding> set_bindings;
178
179 vk::Sampler vk_immutable_sampler =
180 immutable_sampler ? immutable_sampler->GetSampler()
181 : static_cast<vk::Sampler>(VK_NULL_HANDLE);
182
183 for (auto layout : desc.GetVertexDescriptor()->GetDescriptorSetLayouts()) {
184 vk::DescriptorSetLayoutBinding set_binding;
185 set_binding.binding = layout.binding;
186 set_binding.descriptorCount = 1u;
187 set_binding.descriptorType = ToVKDescriptorType(layout.descriptor_type);
188 set_binding.stageFlags = ToVkShaderStage(layout.shader_stage);
189 // TODO(143719): This specifies the immutable sampler for all sampled
190 // images. This is incorrect. In cases where the shader samples from the
191 // multiple images, there is currently no way to tell which sampler needs to
192 // be immutable and which one needs a binding set in the render pass. Expect
193 // errors if the shader has more than on sampled image. The sampling from
194 // the one that is expected to be non-immutable will be incorrect.
195 if (vk_immutable_sampler &&
196 layout.descriptor_type == DescriptorType::kSampledImage) {
197 set_binding.setImmutableSamplers(vk_immutable_sampler);
198 }
199 set_bindings.push_back(set_binding);
200 }
201
202 vk::DescriptorSetLayoutCreateInfo desc_set_layout_info;
203 desc_set_layout_info.setBindings(set_bindings);
204
205 auto [descs_result, descs_layout] =
206 device_holder->GetDevice().createDescriptorSetLayoutUnique(
207 desc_set_layout_info);
208 if (descs_result != vk::Result::eSuccess) {
209 VALIDATION_LOG << "unable to create uniform descriptors";
210 return {fml::Status(fml::StatusCode::kUnknown,
211 "unable to create uniform descriptors")};
212 }
213
214 #ifdef IMPELLER_DEBUG
215 ContextVK::SetDebugName(
216 device_holder->GetDevice(), descs_layout.get(),
217 SPrintF("Descriptor Set Layout: %s", desc.GetLabel().data()));
218 #endif // IMPELLER_DEBUG
219
220 return fml::StatusOr<vk::UniqueDescriptorSetLayout>(std::move(descs_layout));
221 }
222
223 fml::StatusOr<vk::UniquePipelineLayout> MakePipelineLayout(
224 const PipelineDescriptor& desc,
225 const std::shared_ptr<DeviceHolderVK>& device_holder,
226 const vk::DescriptorSetLayout& descs_layout) {
227 vk::PipelineLayoutCreateInfo pipeline_layout_info;
228 pipeline_layout_info.setSetLayouts(descs_layout);
229 auto pipeline_layout = device_holder->GetDevice().createPipelineLayoutUnique(
230 pipeline_layout_info);
231 if (pipeline_layout.result != vk::Result::eSuccess) {
232 VALIDATION_LOG << "Could not create pipeline layout for pipeline "
233 << desc.GetLabel() << ": "
234 << vk::to_string(pipeline_layout.result);
235 return {fml::Status(fml::StatusCode::kUnknown,
236 "Could not create pipeline layout for pipeline.")};
237 }
238
239 #ifdef IMPELLER_DEBUG
240 ContextVK::SetDebugName(
241 device_holder->GetDevice(), *pipeline_layout.value,
242 SPrintF("Pipeline Layout %s", desc.GetLabel().data()));
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 SPrintF("Pipeline %s", desc.GetLabel().data()));
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 std::shared_ptr<SamplerVK> immutable_sampler) {
469 TRACE_EVENT1("flutter", "PipelineVK::Create", "Name", desc.GetLabel().data());
470
471 auto library = weak_library.lock();
472
473 if (!device_holder || !library) {
474 return nullptr;
475 }
476
477 const auto& pso_cache = PipelineLibraryVK::Cast(*library).GetPSOCache();
478
479 fml::StatusOr<vk::UniqueDescriptorSetLayout> descs_layout =
480 MakeDescriptorSetLayout(desc, device_holder, immutable_sampler);
481 if (!descs_layout.ok()) {
482 return nullptr;
483 }
484
485 fml::StatusOr<vk::UniquePipelineLayout> pipeline_layout =
486 MakePipelineLayout(desc, device_holder, descs_layout.value().get());
487 if (!pipeline_layout.ok()) {
488 return nullptr;
489 }
490
491 vk::UniqueRenderPass render_pass =
492 CreateCompatRenderPassForPipeline(device_holder->GetDevice(), desc);
493 if (!render_pass) {
494 VALIDATION_LOG << "Could not create render pass for pipeline.";
495 return nullptr;
496 }
497
498 fml::StatusOr<vk::UniquePipeline> pipeline =
499 MakePipeline(desc, device_holder, pso_cache,
500 pipeline_layout.value().get(), render_pass.get());
501 if (!pipeline.ok()) {
502 return nullptr;
503 }
504
505 auto pipeline_vk = std::unique_ptr<PipelineVK>(new PipelineVK(
506 device_holder, //
507 library, //
508 desc, //
509 std::move(pipeline.value()), //
510 std::move(render_pass), //
511 std::move(pipeline_layout.value()), //
512 std::move(descs_layout.value()), //
513 std::move(immutable_sampler) //
514 ));
515 if (!pipeline_vk->IsValid()) {
516 VALIDATION_LOG << "Could not create a valid pipeline.";
517 return nullptr;
518 }
519 return pipeline_vk;
520 }
521
522 PipelineVK::PipelineVK(std::weak_ptr<DeviceHolderVK> device_holder,
523 std::weak_ptr<PipelineLibrary> library,
524 const PipelineDescriptor& desc,
525 vk::UniquePipeline pipeline,
526 vk::UniqueRenderPass render_pass,
527 vk::UniquePipelineLayout layout,
528 vk::UniqueDescriptorSetLayout descriptor_set_layout,
529 std::shared_ptr<SamplerVK> immutable_sampler)
530 : Pipeline(std::move(library), desc),
531 device_holder_(std::move(device_holder)),
532 pipeline_(std::move(pipeline)),
533 render_pass_(std::move(render_pass)),
534 layout_(std::move(layout)),
535 descriptor_set_layout_(std::move(descriptor_set_layout)),
536 immutable_sampler_(std::move(immutable_sampler)) {
537 is_valid_ = pipeline_ && render_pass_ && layout_ && descriptor_set_layout_;
538 }
539
540 PipelineVK::~PipelineVK() {
541 if (auto device = device_holder_.lock(); !device) {
542 descriptor_set_layout_.release();
543 layout_.release();
544 render_pass_.release();
545 pipeline_.release();
546 }
547 }
548
549 bool PipelineVK::IsValid() const {
550 return is_valid_;
551 }
552
553 vk::Pipeline PipelineVK::GetPipeline() const {
554 return *pipeline_;
555 }
556
557 const vk::PipelineLayout& PipelineVK::GetPipelineLayout() const {
558 return *layout_;
559 }
560
561 const vk::DescriptorSetLayout& PipelineVK::GetDescriptorSetLayout() const {
562 return *descriptor_set_layout_;
563 }
564
565 std::shared_ptr<PipelineVK> PipelineVK::CreateVariantForImmutableSamplers(
566 const std::shared_ptr<SamplerVK>& immutable_sampler) const {
567 if (!immutable_sampler) {
568 return nullptr;
569 }
570 auto cache_key = ImmutableSamplerKeyVK{*immutable_sampler};
571 Lock lock(immutable_sampler_variants_mutex_);
572 auto found = immutable_sampler_variants_.find(cache_key);
573 if (found != immutable_sampler_variants_.end()) {
574 return found->second;
575 }
576 auto device_holder = device_holder_.lock();
577 if (!device_holder) {
578 return nullptr;
579 }
580 return (immutable_sampler_variants_[cache_key] =
581 Create(desc_, device_holder, library_, immutable_sampler));
582 }
583
584 } // namespace impeller
impeller::PipelineDescriptor
Definition: pipeline_descriptor.h:24
timing.h
impeller::Pipeline
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition: compute_pipeline_descriptor.h:18
impeller::CreateCompatRenderPassForPipeline
static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(const vk::Device &device, const PipelineDescriptor &desc)
Definition: pipeline_vk.cc:127
impeller::ImmutableSamplerKeyVK
Definition: yuv_conversion_vk.h:94
impeller::PipelineDescriptor::GetLabel
std::string_view GetLabel() const
Definition: pipeline_descriptor.cc:234
impeller::ReportPipelineCreationFeedbackToLog
static void ReportPipelineCreationFeedbackToLog(std::stringstream &stream, const vk::PipelineCreationFeedbackEXT &feedback)
Definition: pipeline_vk.cc:41
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::ReportPipelineCreationFeedbackToTrace
static void ReportPipelineCreationFeedbackToTrace(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:83
impeller::PipelineVK::~PipelineVK
~PipelineVK() override
Definition: pipeline_vk.cc:540
impeller::RenderPassBuilderVK::SetStencilAttachment
RenderPassBuilderVK & SetStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
Definition: render_pass_builder_vk.cc:91
impeller::ToVKPolygonMode
constexpr vk::PolygonMode ToVKPolygonMode(PolygonMode mode)
Definition: formats_vk.h:370
impeller::ToVKPipelineColorBlendAttachmentState
constexpr vk::PipelineColorBlendAttachmentState ToVKPipelineColorBlendAttachmentState(const ColorAttachmentDescriptor &desc)
Definition: formats_vk.h:113
impeller::PipelineVK::GetPipelineLayout
const vk::PipelineLayout & GetPipelineLayout() const
Definition: pipeline_vk.cc:557
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:292
impeller::PipelineVK::CreateVariantForImmutableSamplers
std::shared_ptr< PipelineVK > CreateVariantForImmutableSamplers(const std::shared_ptr< SamplerVK > &immutable_sampler) const
Definition: pipeline_vk.cc:565
impeller::PipelineVK::GetPipeline
vk::Pipeline GetPipeline() const
Definition: pipeline_vk.cc:553
impeller::Lock
Definition: thread.h:72
impeller::PipelineVK
Definition: pipeline_vk.h:28
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:464
impeller::ToVKCullModeFlags
constexpr vk::CullModeFlags ToVKCullModeFlags(CullMode mode)
Definition: formats_vk.h:441
impeller::PipelineDescriptor::GetSampleCount
SampleCount GetSampleCount() const
Definition: pipeline_descriptor.h:36
impeller::StoreAction::kDontCare
@ kDontCare
impeller::RenderPassBuilderVK
Definition: render_pass_builder_vk.h:21
impeller::EmptyFeedback
static vk::PipelineCreationFeedbackEXT EmptyFeedback()
Definition: pipeline_vk.cc:22
impeller::WindingOrder::kClockwise
@ kClockwise
formats_vk.h
impeller::OptionalDeviceExtensionVK::kEXTPipelineCreationFeedback
@ kEXTPipelineCreationFeedback
pipeline_vk.h
impeller::WindingOrder
WindingOrder
Definition: formats.h:22
impeller::PipelineLibraryVK::GetPSOCache
const std::shared_ptr< PipelineCacheVK > & GetPSOCache() const
Definition: pipeline_library_vk.cc:300
capabilities_vk.h
impeller::RenderPassBuilderVK::SetDepthStencilAttachment
RenderPassBuilderVK & SetDepthStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
Definition: render_pass_builder_vk.cc:73
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)
Definition: render_pass_builder_vk.cc:28
impeller::PrimitiveTopologySupportsPrimitiveRestart
constexpr bool PrimitiveTopologySupportsPrimitiveRestart(PrimitiveType primitive)
Definition: formats_vk.h:380
impeller::PipelineDescriptor::HasStencilAttachmentDescriptors
bool HasStencilAttachmentDescriptors() const
Definition: pipeline_descriptor.cc:247
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::ToVKPrimitiveTopology
constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive)
Definition: formats_vk.h:395
impeller::ToVertexDescriptorFormat
vk::Format ToVertexDescriptorFormat(const ShaderStageIOSlot &input)
Definition: vertex_descriptor_vk.cc:11
render_pass_builder_vk.h
impeller::WindingOrder::kCounterClockwise
@ kCounterClockwise
impeller::ToVKSampleCountFlagBits
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count)
Definition: formats_vk.h:32
impeller::ToVkShaderStage
constexpr vk::ShaderStageFlags ToVkShaderStage(ShaderStage stage)
Definition: formats_vk.h:264
impeller::ContextVK::SetDebugName
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:150
strings.h
impeller::PipelineDescriptor::GetStencilPixelFormat
PixelFormat GetStencilPixelFormat() const
Definition: pipeline_descriptor.cc:197
impeller::DescriptorType::kSampledImage
@ kSampledImage
impeller::Pipeline< PipelineDescriptor >::desc_
const PipelineDescriptor desc_
Definition: pipeline.h:72
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91
impeller::PipelineDescriptor::GetDepthPixelFormat
PixelFormat GetDepthPixelFormat() const
Definition: pipeline_descriptor.cc:238
std
Definition: comparable.h:95
impeller::LoadAction::kDontCare
@ kDontCare
impeller::PipelineDescriptor::GetColorAttachmentDescriptors
const std::map< size_t, ColorAttachmentDescriptor > & GetColorAttachmentDescriptors() const
Definition: pipeline_descriptor.cc:212
impeller::BackendCast< ShaderFunctionVK, ShaderFunction >::Cast
static ShaderFunctionVK & Cast(ShaderFunction &base)
Definition: backend_cast.h:13
impeller::PipelineDescriptor::GetDepthStencilAttachmentDescriptor
std::optional< DepthAttachmentDescriptor > GetDepthStencilAttachmentDescriptor() const
Definition: pipeline_descriptor.cc:207
vertex_descriptor_vk.h
sampler_vk.h
impeller::ToVKFrontFace
constexpr vk::FrontFace ToVKFrontFace(WindingOrder order)
Definition: pipeline_vk.cc:31
impeller::RenderPassBuilderVK::Build
vk::UniqueRenderPass Build(const vk::Device &device) const
Definition: render_pass_builder_vk.cc:109
context_vk.h
impeller::ToVKShaderStageFlagBits
constexpr std::optional< vk::ShaderStageFlagBits > ToVKShaderStageFlagBits(ShaderStage stage)
Definition: formats_vk.h:131
shader_function_vk.h
impeller::PipelineVK::GetDescriptorSetLayout
const vk::DescriptorSetLayout & GetDescriptorSetLayout() const
Definition: pipeline_vk.cc:561
impeller::ReportPipelineCreationFeedback
static void ReportPipelineCreationFeedback(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:106
impeller
Definition: allocation.cc:12
impeller::Pipeline< PipelineDescriptor >::library_
const std::weak_ptr< PipelineLibrary > library_
Definition: pipeline.h:70