7 #include "flutter/fml/make_copyable.h"
8 #include "flutter/fml/trace_event.h"
21 vk::PipelineCreationFeedbackEXT feedback;
25 feedback.flags = vk::PipelineCreationFeedbackFlagBits::eValid;
32 return vk::FrontFace::eClockwise;
34 return vk::FrontFace::eCounterClockwise;
40 std::stringstream& stream,
41 const vk::PipelineCreationFeedbackEXT& feedback) {
42 const auto pipeline_cache_hit =
44 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit;
45 const auto base_pipeline_accl =
47 vk::PipelineCreationFeedbackFlagBits::eBasePipelineAcceleration;
48 auto duration = std::chrono::duration_cast<MillisecondsF>(
49 std::chrono::nanoseconds{feedback.duration});
50 stream <<
"Time: " << duration.count() <<
"ms"
51 <<
" Cache Hit: " <<
static_cast<bool>(pipeline_cache_hit)
52 <<
" Base Accel: " <<
static_cast<bool>(base_pipeline_accl)
53 <<
" Thread: " << std::this_thread::get_id();
58 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
59 std::stringstream stream;
60 stream << std::fixed << std::showpoint << std::setprecision(2);
61 stream << std::endl <<
">>>>>>" << std::endl;
62 stream <<
"Pipeline '" << desc.
GetLabel() <<
"' ";
64 *feedback.pPipelineCreationFeedback);
65 if (feedback.pipelineStageCreationFeedbackCount != 0) {
68 for (
size_t i = 0, count = feedback.pipelineStageCreationFeedbackCount;
70 stream <<
"\tStage " << i + 1 <<
": ";
72 stream, feedback.pPipelineStageCreationFeedbacks[i]);
77 stream << std::endl <<
"<<<<<<" << std::endl;
78 FML_LOG(ERROR) << stream.str();
83 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
84 static int64_t gPipelineCacheHits = 0;
85 static int64_t gPipelineCacheMisses = 0;
86 static int64_t gPipelines = 0;
87 if (feedback.pPipelineCreationFeedback->flags &
88 vk::PipelineCreationFeedbackFlagBits::eApplicationPipelineCacheHit) {
91 gPipelineCacheMisses++;
94 static constexpr int64_t kImpellerPipelineTraceID = 1988;
95 FML_TRACE_COUNTER(
"impeller",
97 kImpellerPipelineTraceID,
98 "PipelineCacheHits", gPipelineCacheHits,
99 "PipelineCacheMisses", gPipelineCacheMisses,
100 "TotalPipelines", gPipelines
106 const vk::PipelineCreationFeedbackCreateInfoEXT& feedback) {
107 constexpr
bool kReportPipelineCreationFeedbackToLogs =
false;
108 constexpr
bool kReportPipelineCreationFeedbackToTraces =
true;
109 if (kReportPipelineCreationFeedbackToLogs) {
112 if (kReportPipelineCreationFeedbackToTraces) {
126 const vk::Device& device,
154 auto pass = builder.
Build(device);
162 "Compat Render Pass: " + desc.
GetLabel());
169 const std::shared_ptr<DeviceHolderVK>& device_holder,
170 const std::weak_ptr<PipelineLibrary>& weak_library,
171 std::shared_ptr<SamplerVK> immutable_sampler) {
172 TRACE_EVENT0(
"flutter",
"PipelineVK::Create");
174 auto library = weak_library.lock();
176 if (!device_holder || !library) {
182 vk::StructureChain<vk::GraphicsPipelineCreateInfo,
183 vk::PipelineCreationFeedbackCreateInfoEXT>
186 const auto* caps = pso_cache->GetCapabilities();
188 const auto supports_pipeline_creation_feedback = caps->HasExtension(
190 if (!supports_pipeline_creation_feedback) {
191 chain.unlink<vk::PipelineCreationFeedbackCreateInfoEXT>();
194 auto& pipeline_info = chain.get<vk::GraphicsPipelineCreateInfo>();
199 vk::PipelineDynamicStateCreateInfo dynamic_create_state_info;
200 std::vector<vk::DynamicState> dynamic_states = {
201 vk::DynamicState::eViewport,
202 vk::DynamicState::eScissor,
203 vk::DynamicState::eStencilReference,
205 dynamic_create_state_info.setDynamicStates(dynamic_states);
206 pipeline_info.setPDynamicState(&dynamic_create_state_info);
211 vk::PipelineViewportStateCreateInfo viewport_state;
212 viewport_state.setViewportCount(1u);
213 viewport_state.setScissorCount(1u);
216 pipeline_info.setPViewportState(&viewport_state);
223 std::vector<std::vector<vk::SpecializationMapEntry>> map_entries(
225 std::vector<vk::SpecializationInfo> specialization_infos(
227 std::vector<vk::PipelineShaderStageCreateInfo> shader_stages;
229 size_t entrypoint_count = 0;
232 if (!stage.has_value()) {
238 std::vector<vk::SpecializationMapEntry>& entries =
239 map_entries[entrypoint_count];
240 for (
auto i = 0u; i < constants.size(); i++) {
241 vk::SpecializationMapEntry entry;
242 entry.offset = (i *
sizeof(
Scalar));
243 entry.size =
sizeof(
Scalar);
244 entry.constantID = i;
245 entries.emplace_back(entry);
248 vk::SpecializationInfo& specialization_info =
249 specialization_infos[entrypoint_count];
250 specialization_info.setMapEntries(map_entries[entrypoint_count]);
251 specialization_info.setPData(constants.data());
252 specialization_info.setDataSize(
sizeof(
Scalar) * constants.size());
254 vk::PipelineShaderStageCreateInfo info;
255 info.setStage(stage.value());
256 info.setPName(
"main");
259 info.setPSpecializationInfo(&specialization_info);
260 shader_stages.push_back(info);
263 pipeline_info.setStages(shader_stages);
268 vk::PipelineRasterizationStateCreateInfo rasterization_state;
272 rasterization_state.setLineWidth(1.0f);
273 rasterization_state.setDepthClampEnable(
false);
274 rasterization_state.setRasterizerDiscardEnable(
false);
275 pipeline_info.setPRasterizationState(&rasterization_state);
280 vk::PipelineMultisampleStateCreateInfo multisample_state;
281 multisample_state.setRasterizationSamples(
283 pipeline_info.setPMultisampleState(&multisample_state);
287 vk::PipelineInputAssemblyStateCreateInfo input_assembly;
289 input_assembly.setTopology(topology);
290 pipeline_info.setPInputAssemblyState(&input_assembly);
294 std::vector<vk::PipelineColorBlendAttachmentState> attachment_blend_state;
299 attachment_blend_state.push_back(
302 vk::PipelineColorBlendStateCreateInfo blend_state;
303 blend_state.setAttachments(attachment_blend_state);
304 pipeline_info.setPColorBlendState(&blend_state);
319 pipeline_info.setBasePipelineHandle(VK_NULL_HANDLE);
320 pipeline_info.setSubpass(0u);
321 pipeline_info.setRenderPass(render_pass.get());
326 std::vector<vk::VertexInputAttributeDescription> attr_descs;
327 std::vector<vk::VertexInputBindingDescription> buffer_descs;
330 const auto& stage_buffer_layouts =
333 vk::VertexInputAttributeDescription attr_desc;
334 attr_desc.setBinding(stage_in.binding);
335 attr_desc.setLocation(stage_in.location);
337 attr_desc.setOffset(stage_in.offset);
338 attr_descs.push_back(attr_desc);
341 vk::VertexInputBindingDescription binding_description;
342 binding_description.setBinding(layout.binding);
343 binding_description.setInputRate(vk::VertexInputRate::eVertex);
344 binding_description.setStride(layout.stride);
345 buffer_descs.push_back(binding_description);
348 vk::PipelineVertexInputStateCreateInfo vertex_input_state;
349 vertex_input_state.setVertexAttributeDescriptions(attr_descs);
350 vertex_input_state.setVertexBindingDescriptions(buffer_descs);
352 pipeline_info.setPVertexInputState(&vertex_input_state);
357 std::vector<vk::DescriptorSetLayoutBinding> set_bindings;
359 vk::Sampler vk_immutable_sampler =
360 immutable_sampler ? immutable_sampler->GetSampler()
361 :
static_cast<vk::Sampler
>(VK_NULL_HANDLE);
364 vk::DescriptorSetLayoutBinding set_binding;
365 set_binding.binding = layout.binding;
366 set_binding.descriptorCount = 1u;
375 if (vk_immutable_sampler &&
377 set_binding.setImmutableSamplers(vk_immutable_sampler);
379 set_bindings.push_back(set_binding);
382 vk::DescriptorSetLayoutCreateInfo desc_set_layout_info;
383 desc_set_layout_info.setBindings(set_bindings);
385 auto [descs_result, descs_layout] =
386 device_holder->GetDevice().createDescriptorSetLayoutUnique(
387 desc_set_layout_info);
388 if (descs_result != vk::Result::eSuccess) {
394 "Descriptor Set Layout " + desc.
GetLabel());
399 vk::PipelineLayoutCreateInfo pipeline_layout_info;
400 pipeline_layout_info.setSetLayouts(descs_layout.get());
401 auto pipeline_layout = device_holder->GetDevice().createPipelineLayoutUnique(
402 pipeline_layout_info);
403 if (pipeline_layout.result != vk::Result::eSuccess) {
404 VALIDATION_LOG <<
"Could not create pipeline layout for pipeline "
406 << vk::to_string(pipeline_layout.result);
409 pipeline_info.setLayout(pipeline_layout.value.get());
418 pipeline_info.setPDepthStencilState(&depth_stencil_state);
424 auto& feedback = chain.get<vk::PipelineCreationFeedbackCreateInfoEXT>();
426 std::vector<vk::PipelineCreationFeedbackEXT> stage_feedbacks(
428 feedback.setPPipelineCreationFeedback(&pipeline_feedback);
429 feedback.setPipelineStageCreationFeedbacks(stage_feedbacks);
434 auto pipeline = pso_cache->CreatePipeline(pipeline_info);
440 if (supports_pipeline_creation_feedback) {
445 "Pipeline Layout " + desc.
GetLabel());
449 auto pipeline_vk = std::unique_ptr<PipelineVK>(
new PipelineVK(
454 std::move(render_pass),
455 std::move(pipeline_layout.value),
456 std::move(descs_layout),
457 std::move(immutable_sampler)
459 if (!pipeline_vk->IsValid()) {
466 PipelineVK::PipelineVK(std::weak_ptr<DeviceHolderVK> device_holder,
467 std::weak_ptr<PipelineLibrary> library,
469 vk::UniquePipeline pipeline,
470 vk::UniqueRenderPass render_pass,
471 vk::UniquePipelineLayout layout,
472 vk::UniqueDescriptorSetLayout descriptor_set_layout,
473 std::shared_ptr<SamplerVK> immutable_sampler)
475 device_holder_(
std::move(device_holder)),
476 pipeline_(
std::move(pipeline)),
477 render_pass_(
std::move(render_pass)),
478 layout_(
std::move(layout)),
479 descriptor_set_layout_(
std::move(descriptor_set_layout)),
480 immutable_sampler_(
std::move(immutable_sampler)) {
481 is_valid_ = pipeline_ && render_pass_ && layout_ && descriptor_set_layout_;
485 if (
auto device = device_holder_.lock(); !device) {
486 descriptor_set_layout_.release();
488 render_pass_.release();
493 bool PipelineVK::IsValid()
const {
506 return *descriptor_set_layout_;
510 const std::shared_ptr<SamplerVK>& immutable_sampler)
const {
511 if (!immutable_sampler) {
515 Lock lock(immutable_sampler_variants_mutex_);
516 auto found = immutable_sampler_variants_.find(cache_key);
517 if (found != immutable_sampler_variants_.end()) {
518 return found->second;
520 auto device_holder = device_holder_.lock();
521 if (!device_holder) {
524 return (immutable_sampler_variants_[cache_key] =