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 
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"
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) {
35  return vk::FrontFace::eClockwise;
37  return vk::FrontFace::eCounterClockwise;
38  }
39  FML_UNREACHABLE();
40 }
41 
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 
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() << "' ";
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 << ": ";
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 
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 
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) {
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(), //
139  );
140  }
141 
142  if (auto depth = desc.GetDepthStencilAttachmentDescriptor();
143  depth.has_value()) {
145  desc.GetSampleCount(), //
148  );
149  } else if (desc.HasStencilAttachmentDescriptors()) {
151  desc.GetSampleCount(), //
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
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
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(
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 
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 
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
static ShaderFunctionVK & Cast(ShaderFunction &base)
Definition: backend_cast.h:13
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:151
std::string_view GetLabel() const
PixelFormat GetDepthPixelFormat() const
std::optional< DepthAttachmentDescriptor > GetDepthStencilAttachmentDescriptor() const
PixelFormat GetStencilPixelFormat() const
const std::map< size_t, ColorAttachmentDescriptor > & GetColorAttachmentDescriptors() const
SampleCount GetSampleCount() const
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition: pipeline.h:52
const std::weak_ptr< PipelineLibrary > library_
Definition: pipeline.h:72
const PipelineDescriptor desc_
Definition: pipeline.h:74
const std::shared_ptr< PipelineCacheVK > & GetPSOCache() const
std::shared_ptr< PipelineVK > CreateVariantForImmutableSamplers(const std::shared_ptr< SamplerVK > &immutable_sampler) const
Definition: pipeline_vk.cc:570
~PipelineVK() override
Definition: pipeline_vk.cc:545
const vk::PipelineLayout & GetPipelineLayout() const
Definition: pipeline_vk.cc:562
const vk::DescriptorSetLayout & GetDescriptorSetLayout() const
Definition: pipeline_vk.cc:566
vk::Pipeline GetPipeline() const
Definition: pipeline_vk.cc:558
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
RenderPassBuilderVK & SetDepthStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
RenderPassBuilderVK & SetStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
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)
vk::UniqueRenderPass Build(const vk::Device &device) const
float Scalar
Definition: scalar.h:19
vk::Format ToVertexDescriptorFormat(const ShaderStageIOSlot &input)
static void ReportPipelineCreationFeedback(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:107
constexpr vk::PipelineColorBlendAttachmentState ToVKPipelineColorBlendAttachmentState(const ColorAttachmentDescriptor &desc)
Definition: formats_vk.h:113
static vk::PipelineCreationFeedbackEXT EmptyFeedback()
Definition: pipeline_vk.cc:23
int64_t PipelineKey
Definition: pipeline.h:21
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count)
Definition: formats_vk.h:32
constexpr std::optional< vk::ShaderStageFlagBits > ToVKShaderStageFlagBits(ShaderStage stage)
Definition: formats_vk.h:131
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:292
constexpr vk::PolygonMode ToVKPolygonMode(PolygonMode mode)
Definition: formats_vk.h:370
constexpr vk::CullModeFlags ToVKCullModeFlags(CullMode mode)
Definition: formats_vk.h:441
static void ReportPipelineCreationFeedbackToLog(std::stringstream &stream, const vk::PipelineCreationFeedbackEXT &feedback)
Definition: pipeline_vk.cc:42
vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo(std::optional< DepthAttachmentDescriptor > depth, std::optional< StencilAttachmentDescriptor > front, std::optional< StencilAttachmentDescriptor > back)
Definition: formats_vk.cc:9
constexpr bool PrimitiveTopologySupportsPrimitiveRestart(PrimitiveType primitive)
Definition: formats_vk.h:380
WindingOrder
Definition: formats.h:22
constexpr vk::FrontFace ToVKFrontFace(WindingOrder order)
Definition: pipeline_vk.cc:32
constexpr vk::ShaderStageFlags ToVkShaderStage(ShaderStage stage)
Definition: formats_vk.h:264
constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive)
Definition: formats_vk.h:395
static void ReportPipelineCreationFeedbackToTrace(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
Definition: pipeline_vk.cc:84
static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(const vk::Device &device, const PipelineDescriptor &desc)
Definition: pipeline_vk.cc:128
Definition: comparable.h:95
#define VALIDATION_LOG
Definition: validation.h:91