diff --git a/docs/features.txt b/docs/features.txt index f1a37815c19..7aad2e89948 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -485,7 +485,7 @@ Vulkan 1.3 -- all DONE: anv, radv, lvp VK_EXT_extended_dynamic_state2 DONE (anv, lvp, radv, tu) VK_EXT_inline_uniform_block DONE (anv, radv, v3dv) VK_EXT_pipeline_creation_cache_control DONE (anv, radv, v3dv) - VK_EXT_pipeline_creation_feedback DONE (anv, radv, v3dv) + VK_EXT_pipeline_creation_feedback DONE (anv, radv, tu, v3dv) VK_EXT_private_data DONE (anv, lvp, radv, tu, v3dv) VK_EXT_image_robustness DONE (anv, radv, tu) VK_EXT_shader_demote_to_helper_invocation DONE (anv, radv, tu) diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index 018c85d3663..4e29c42aa60 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -216,6 +216,7 @@ get_device_extensions(const struct tu_physical_device *device, .EXT_image_robustness = true, .EXT_primitives_generated_query = true, .EXT_image_view_min_lod = true, + .EXT_pipeline_creation_feedback = true, #ifndef TU_USE_KGSL .EXT_physical_device_drm = true, #endif diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index 294a9b2073c..3e22ebcabbb 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -2660,11 +2660,12 @@ tu_shaders_deserialize(struct vk_device *_device, static struct tu_compiled_shaders * tu_pipeline_cache_lookup(struct vk_pipeline_cache *cache, - const void *key_data, size_t key_size) + const void *key_data, size_t key_size, + bool *application_cache_hit) { struct vk_pipeline_cache_object *object = vk_pipeline_cache_lookup_object(cache, key_data, key_size, - &tu_shaders_ops, NULL); + &tu_shaders_ops, application_cache_hit); if (object) return container_of(object, struct tu_compiled_shaders, base); else @@ -2689,6 +2690,16 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, const VkPipelineShaderStageCreateInfo *stage_infos[MESA_SHADER_STAGES] = { NULL }; + VkPipelineCreationFeedbackEXT pipeline_feedback = { + .flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + }; + VkPipelineCreationFeedbackEXT stage_feedbacks[MESA_SHADER_STAGES] = { 0 }; + + int64_t pipeline_start = os_time_get_nano(); + + const VkPipelineCreationFeedbackCreateInfo *creation_feedback = + vk_find_struct_const(builder->create_info->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO); + for (uint32_t i = 0; i < builder->create_info->stageCount; i++) { gl_shader_stage stage = vk_to_mesa_shader_stage(builder->create_info->pStages[i].stage); @@ -2718,9 +2729,17 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, struct tu_compiled_shaders *compiled_shaders; if (!executable_info) { + bool application_cache_hit = false; + compiled_shaders = tu_pipeline_cache_lookup(builder->cache, &pipeline_sha1, - sizeof(pipeline_sha1)); + sizeof(pipeline_sha1), + &application_cache_hit); + + if (application_cache_hit && builder->cache != builder->device->mem_cache) { + pipeline_feedback.flags |= + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT; + } if (compiled_shaders) goto done; @@ -2736,11 +2755,16 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, if (!stage_info) continue; + int64_t stage_start = os_time_get_nano(); + nir[stage] = tu_spirv_to_nir(builder->device, builder->mem_ctx, stage_info, stage); if (!nir[stage]) { result = VK_ERROR_OUT_OF_HOST_MEMORY; goto fail; } + + stage_feedbacks[stage].flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT; + stage_feedbacks[stage].duration += os_time_get_nano() - stage_start; } if (!nir[MESA_SHADER_FRAGMENT]) { @@ -2771,6 +2795,8 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, if (!nir[stage]) continue; + int64_t stage_start = os_time_get_nano(); + struct tu_shader *shader = tu_shader_create(builder->device, nir[stage], &keys[stage], builder->layout, builder->alloc); @@ -2802,6 +2828,8 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, desc_sets |= shader->active_desc_sets; shaders[stage] = shader; + + stage_feedbacks[stage].duration += os_time_get_nano() - stage_start; } struct tu_shader *last_shader = shaders[MESA_SHADER_GEOMETRY]; @@ -2832,6 +2860,8 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, if (!shaders[stage]) continue; + int64_t stage_start = os_time_get_nano(); + compiled_shaders->variants[stage] = ir3_shader_create_variant(shaders[stage]->ir3_shader, &ir3_key, executable_info); @@ -2839,6 +2869,8 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, return VK_ERROR_OUT_OF_HOST_MEMORY; compiled_shaders->push_consts[stage] = shaders[stage]->push_consts; + + stage_feedbacks[stage].duration += os_time_get_nano() - stage_start; } uint32_t safe_constlens = ir3_trim_constlen(compiled_shaders->variants, compiler); @@ -2851,6 +2883,8 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, continue; if (safe_constlens & (1 << stage)) { + int64_t stage_start = os_time_get_nano(); + ralloc_free(compiled_shaders->variants[stage]); compiled_shaders->variants[stage] = ir3_shader_create_variant(shaders[stage]->ir3_shader, &ir3_key, @@ -2859,6 +2893,8 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, result = VK_ERROR_OUT_OF_HOST_MEMORY; goto fail; } + + stage_feedbacks[stage].duration += os_time_get_nano() - stage_start; } } @@ -2902,6 +2938,19 @@ done: compiled_shaders->variants[MESA_SHADER_TESS_CTRL]->key.tessellation; } + pipeline_feedback.duration = os_time_get_nano() - pipeline_start; + if (creation_feedback) { + *creation_feedback->pPipelineCreationFeedback = pipeline_feedback; + + assert(builder->create_info->stageCount == + creation_feedback->pipelineStageCreationFeedbackCount); + for (uint32_t i = 0; i < builder->create_info->stageCount; i++) { + gl_shader_stage s = + vk_to_mesa_shader_stage(builder->create_info->pStages[i].stage); + creation_feedback->pPipelineStageCreationFeedbacks[i] = stage_feedbacks[s]; + } + } + return VK_SUCCESS; fail: @@ -3820,6 +3869,15 @@ tu_compute_pipeline_create(VkDevice device, *pPipeline = VK_NULL_HANDLE; + VkPipelineCreationFeedbackEXT pipeline_feedback = { + .flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + }; + + const VkPipelineCreationFeedbackCreateInfo *creation_feedback = + vk_find_struct_const(pCreateInfo->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO); + + int64_t pipeline_start = os_time_get_nano(); + pipeline = vk_object_zalloc(&dev->vk, pAllocator, sizeof(*pipeline), VK_OBJECT_TYPE_PIPELINE); if (!pipeline) @@ -3841,8 +3899,18 @@ tu_compute_pipeline_create(VkDevice device, const bool executable_info = pCreateInfo->flags & VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR; - if (!executable_info) - compiled = tu_pipeline_cache_lookup(cache, pipeline_sha1, sizeof(pipeline_sha1)); + bool application_cache_hit = false; + + if (!executable_info) { + compiled = + tu_pipeline_cache_lookup(cache, pipeline_sha1, sizeof(pipeline_sha1), + &application_cache_hit); + } + + if (application_cache_hit && cache != dev->mem_cache) { + pipeline_feedback.flags |= + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT; + } char *nir_initial_disasm = NULL; @@ -3887,6 +3955,14 @@ tu_compute_pipeline_create(VkDevice device, compiled = tu_pipeline_cache_insert(cache, compiled); } + pipeline_feedback.duration = os_time_get_nano() - pipeline_start; + + if (creation_feedback) { + *creation_feedback->pPipelineCreationFeedback = pipeline_feedback; + assert(creation_feedback->pipelineStageCreationFeedbackCount == 1); + creation_feedback->pPipelineStageCreationFeedbacks[0] = pipeline_feedback; + } + pipeline->active_desc_sets = compiled->active_desc_sets; struct ir3_shader_variant *v = compiled->variants[MESA_SHADER_COMPUTE];