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