7#include "flutter/fml/make_copyable.h"
8#include "flutter/fml/status_or.h"
9#include "flutter/fml/trace_event.h"
22 vk::PipelineCreationFeedbackEXT feedback;
26 feedback.flags = vk::PipelineCreationFeedbackFlagBits::eValid;
33 return vk::FrontFace::eClockwise;
35 return vk::FrontFace::eCounterClockwise;
42 const vk::PipelineCreationFeedbackEXT& feedback) {
43 const auto pipeline_cache_hit =
45 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit;
46 const auto base_pipeline_accl =
48 vk::PipelineCreationFeedbackFlagBits::eBasePipelineAcceleration;
49 auto duration = std::chrono::duration_cast<MillisecondsF>(
50 std::chrono::nanoseconds{feedback.duration});
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();
59 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
61 stream << std::fixed << std::showpoint << std::setprecision(2);
62 stream << std::endl <<
">>>>>>" << std::endl;
63 stream <<
"Pipeline '" <<
desc.GetLabel() <<
"' ";
65 *feedback.pPipelineCreationFeedback);
66 if (feedback.pipelineStageCreationFeedbackCount != 0) {
69 for (
size_t i = 0,
count = feedback.pipelineStageCreationFeedbackCount;
71 stream <<
"\tStage " <<
i + 1 <<
": ";
73 stream, feedback.pPipelineStageCreationFeedbacks[
i]);
78 stream << std::endl <<
"<<<<<<" << std::endl;
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) {
92 gPipelineCacheMisses++;
95 static constexpr int64_t kImpellerPipelineTraceID = 1988;
98 kImpellerPipelineTraceID,
99 "PipelineCacheHits", gPipelineCacheHits,
100 "PipelineCacheMisses", gPipelineCacheMisses,
101 "TotalPipelines", gPipelines
107 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
108 constexpr bool kReportPipelineCreationFeedbackToLogs =
false;
109 constexpr bool kReportPipelineCreationFeedbackToTraces =
true;
110 if (kReportPipelineCreationFeedbackToLogs) {
113 if (kReportPipelineCreationFeedbackToTraces) {
131 for (
const auto& [bind_point,
color] :
desc.GetColorAttachmentDescriptors()) {
132 builder.SetColorAttachment(bind_point,
134 desc.GetSampleCount(),
140 if (
auto depth =
desc.GetDepthStencilAttachmentDescriptor();
142 builder.SetDepthStencilAttachment(
desc.GetDepthPixelFormat(),
143 desc.GetSampleCount(),
147 }
else if (
desc.HasStencilAttachmentDescriptors()) {
148 builder.SetStencilAttachment(
desc.GetStencilPixelFormat(),
149 desc.GetSampleCount(),
163 "Compat Render Pass: " +
desc.GetLabel());
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;
176 immutable_sampler ? immutable_sampler->GetSampler()
179 for (
auto layout :
desc.GetVertexDescriptor()->GetDescriptorSetLayouts()) {
180 vk::DescriptorSetLayoutBinding set_binding;
181 set_binding.binding = layout.binding;
182 set_binding.descriptorCount = 1u;
191 if (vk_immutable_sampler &&
193 set_binding.setImmutableSamplers(vk_immutable_sampler);
195 set_bindings.push_back(set_binding);
198 vk::DescriptorSetLayoutCreateInfo desc_set_layout_info;
199 desc_set_layout_info.setBindings(set_bindings);
201 auto [descs_result, descs_layout] =
202 device_holder->GetDevice().createDescriptorSetLayoutUnique(
203 desc_set_layout_info);
204 if (descs_result != vk::Result::eSuccess) {
207 "unable to create uniform descriptors")};
211 "Descriptor Set Layout " +
desc.GetLabel());
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() <<
": "
229 "Could not create pipeline layout for pipeline.")};
233 "Pipeline Layout " +
desc.GetLabel());
235 return std::move(pipeline_layout.value);
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>
248 const auto* caps = pso_cache->GetCapabilities();
250 const auto supports_pipeline_creation_feedback = caps->HasExtension(
252 if (!supports_pipeline_creation_feedback) {
253 chain.unlink<vk::PipelineCreationFeedbackCreateInfoEXT>();
256 auto& pipeline_info = chain.get<vk::GraphicsPipelineCreateInfo>();
257 pipeline_info.setLayout(pipeline_layout);
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,
268 dynamic_create_state_info.setDynamicStates(dynamic_states);
269 pipeline_info.setPDynamicState(&dynamic_create_state_info);
274 vk::PipelineViewportStateCreateInfo viewport_state;
275 viewport_state.setViewportCount(1u);
276 viewport_state.setScissorCount(1u);
279 pipeline_info.setPViewportState(&viewport_state);
284 const auto& constants =
desc.GetSpecializationConstants();
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;
292 size_t entrypoint_count = 0;
293 for (
const auto& entrypoint :
desc.GetStageEntrypoints()) {
295 if (!stage.has_value()) {
299 "Unsupported shader type in pipeline.")};
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);
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());
318 vk::PipelineShaderStageCreateInfo
info;
319 info.setStage(stage.value());
320 info.setPName(
"main");
323 info.setPSpecializationInfo(&specialization_info);
324 shader_stages.push_back(
info);
327 pipeline_info.setStages(shader_stages);
332 vk::PipelineRasterizationStateCreateInfo rasterization_state;
336 rasterization_state.setLineWidth(1.0f);
337 rasterization_state.setDepthClampEnable(
false);
338 rasterization_state.setRasterizerDiscardEnable(
false);
339 pipeline_info.setPRasterizationState(&rasterization_state);
344 vk::PipelineMultisampleStateCreateInfo multisample_state;
345 multisample_state.setRasterizationSamples(
347 pipeline_info.setPMultisampleState(&multisample_state);
351 vk::PipelineInputAssemblyStateCreateInfo input_assembly;
353 input_assembly.setTopology(topology);
354 pipeline_info.setPInputAssemblyState(&input_assembly);
358 std::vector<vk::PipelineColorBlendAttachmentState> attachment_blend_state;
359 for (
const auto& color_desc :
desc.GetColorAttachmentDescriptors()) {
363 attachment_blend_state.push_back(
366 vk::PipelineColorBlendStateCreateInfo blend_state;
367 blend_state.setAttachments(attachment_blend_state);
368 pipeline_info.setPColorBlendState(&blend_state);
374 pipeline_info.setSubpass(0u);
375 pipeline_info.setRenderPass(render_pass);
380 std::vector<vk::VertexInputAttributeDescription> attr_descs;
381 std::vector<vk::VertexInputBindingDescription> buffer_descs;
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);
391 attr_desc.setOffset(stage_in.offset);
392 attr_descs.push_back(attr_desc);
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);
402 vk::PipelineVertexInputStateCreateInfo vertex_input_state;
403 vertex_input_state.setVertexAttributeDescriptions(attr_descs);
404 vertex_input_state.setVertexBindingDescriptions(buffer_descs);
406 pipeline_info.setPVertexInputState(&vertex_input_state);
412 desc.GetDepthStencilAttachmentDescriptor(),
413 desc.GetFrontStencilAttachmentDescriptor(),
414 desc.GetBackStencilAttachmentDescriptor());
415 pipeline_info.setPDepthStencilState(&depth_stencil_state);
421 auto& feedback = chain.get<vk::PipelineCreationFeedbackCreateInfoEXT>();
423 std::vector<vk::PipelineCreationFeedbackEXT> stage_feedbacks(
425 feedback.setPPipelineCreationFeedback(&pipeline_feedback);
426 feedback.setPipelineStageCreationFeedbacks(stage_feedbacks);
431 auto pipeline = pso_cache->CreatePipeline(pipeline_info);
435 "Could not create graphics pipeline.")};
438 if (supports_pipeline_creation_feedback) {
443 "Pipeline " +
desc.GetLabel());
445 return std::move(pipeline);
451 const std::shared_ptr<DeviceHolderVK>& device_holder,
452 const std::weak_ptr<PipelineLibrary>& weak_library,
453 std::shared_ptr<SamplerVK> immutable_sampler) {
456 auto library = weak_library.lock();
458 if (!device_holder || !library) {
465 MakeDescriptorSetLayout(
desc, device_holder, immutable_sampler);
466 if (!descs_layout.
ok()) {
471 MakePipelineLayout(
desc, device_holder, descs_layout.
value().get());
472 if (!pipeline_layout.
ok()) {
476 vk::UniqueRenderPass render_pass =
484 MakePipeline(
desc, device_holder, pso_cache,
485 pipeline_layout.
value().get(), render_pass.get());
486 if (!pipeline.
ok()) {
490 auto pipeline_vk = std::unique_ptr<PipelineVK>(
new PipelineVK(
494 std::move(pipeline.
value()),
495 std::move(render_pass),
496 std::move(pipeline_layout.
value()),
497 std::move(descs_layout.
value()),
498 std::move(immutable_sampler)
500 if (!pipeline_vk->IsValid()) {
507PipelineVK::PipelineVK(std::weak_ptr<DeviceHolderVK> device_holder,
508 std::weak_ptr<PipelineLibrary> library,
510 vk::UniquePipeline pipeline,
511 vk::UniqueRenderPass render_pass,
512 vk::UniquePipelineLayout layout,
513 vk::UniqueDescriptorSetLayout descriptor_set_layout,
514 std::shared_ptr<SamplerVK> immutable_sampler)
516 device_holder_(
std::move(device_holder)),
517 pipeline_(
std::move(pipeline)),
518 render_pass_(
std::move(render_pass)),
520 descriptor_set_layout_(
std::move(descriptor_set_layout)),
521 immutable_sampler_(
std::move(immutable_sampler)) {
522 is_valid_ = pipeline_ && render_pass_ && layout_ && descriptor_set_layout_;
527 descriptor_set_layout_.release();
529 render_pass_.release();
534bool PipelineVK::IsValid()
const {
547 return *descriptor_set_layout_;
551 const std::shared_ptr<SamplerVK>& immutable_sampler)
const {
552 if (!immutable_sampler) {
556 Lock lock(immutable_sampler_variants_mutex_);
557 auto found = immutable_sampler_variants_.find(cache_key);
558 if (found != immutable_sampler_variants_.end()) {
559 return found->second;
561 auto device_holder = device_holder_.lock();
562 if (!device_holder) {
565 return (immutable_sampler_variants_[cache_key] =
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static ShaderFunctionVK & Cast(ShaderFunction &base)
bool SetDebugName(T handle, std::string_view label) const
const std::shared_ptr< PipelineCacheVK > & GetPSOCache() const
std::shared_ptr< PipelineVK > CreateVariantForImmutableSamplers(const std::shared_ptr< SamplerVK > &immutable_sampler) const
const vk::PipelineLayout & GetPipelineLayout() const
const vk::DescriptorSetLayout & GetDescriptorSetLayout() const
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={})
vk::Pipeline GetPipeline() const
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
const std::weak_ptr< PipelineLibrary > library_
const PipelineDescriptor desc_
#define FML_LOG(severity)
#define FML_UNREACHABLE()
std::function< ProfileSample(void)> Sampler
Sampler is run during SamplingProfiler::SampleRepeatedly. Each platform should implement its version ...
vk::Format ToVertexDescriptorFormat(const ShaderStageIOSlot &input)
static void ReportPipelineCreationFeedback(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
constexpr vk::PipelineColorBlendAttachmentState ToVKPipelineColorBlendAttachmentState(const ColorAttachmentDescriptor &desc)
static vk::PipelineCreationFeedbackEXT EmptyFeedback()
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count)
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
constexpr vk::PolygonMode ToVKPolygonMode(PolygonMode mode)
constexpr vk::CullModeFlags ToVKCullModeFlags(CullMode mode)
static void ReportPipelineCreationFeedbackToLog(std::stringstream &stream, const vk::PipelineCreationFeedbackEXT &feedback)
vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo(std::optional< DepthAttachmentDescriptor > depth, std::optional< StencilAttachmentDescriptor > front, std::optional< StencilAttachmentDescriptor > back)
constexpr std::optional< vk::ShaderStageFlagBits > ToVKShaderStageFlagBits(ShaderStage stage)
constexpr vk::FrontFace ToVKFrontFace(WindingOrder order)
constexpr vk::ShaderStageFlags ToVkShaderStage(ShaderStage stage)
constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive)
static void ReportPipelineCreationFeedbackToTrace(const PipelineDescriptor &desc, const vk::PipelineCreationFeedbackCreateInfoEXT &feedback)
static vk::UniqueRenderPass CreateCompatRenderPassForPipeline(const vk::Device &device, const PipelineDescriptor &desc)
@ kEXTPipelineCreationFeedback
static SkString to_string(int n)
#define TRACE_EVENT0(category_group, name)
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)