Mesa (master): radv: Implement VK_EXT_pipeline_creation_feedback.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Mar 20 21:30:20 UTC 2019


Module: Mesa
Branch: master
Commit: 5f5ac19f138125b04d8ddedd6334b996f8925a4a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5f5ac19f138125b04d8ddedd6334b996f8925a4a

Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date:   Tue Mar 19 02:30:33 2019 +0100

radv: Implement VK_EXT_pipeline_creation_feedback.

Does what it says on the tin.

The per stage time is only an approximation due to linking and
the Vega merged stages.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>

---

 src/amd/vulkan/radv_device.c         |  2 +-
 src/amd/vulkan/radv_extensions.py    |  1 +
 src/amd/vulkan/radv_pipeline.c       | 99 ++++++++++++++++++++++++++++++++++--
 src/amd/vulkan/radv_pipeline_cache.c |  9 +++-
 src/amd/vulkan/radv_private.h        |  5 +-
 5 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index dc4346b7498..52c688315a7 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -3647,7 +3647,7 @@ void radv_DestroyFence(
 }
 
 
-static uint64_t radv_get_current_time()
+uint64_t radv_get_current_time(void)
 {
 	struct timespec tv;
 	clock_gettime(CLOCK_MONOTONIC, &tv);
diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_extensions.py
index 1fae95a5de1..88d5780fe8d 100644
--- a/src/amd/vulkan/radv_extensions.py
+++ b/src/amd/vulkan/radv_extensions.py
@@ -112,6 +112,7 @@ EXTENSIONS = [
     Extension('VK_EXT_memory_budget',                     1, True),
     Extension('VK_EXT_memory_priority',                   1, True),
     Extension('VK_EXT_pci_bus_info',                      2, True),
+    Extension('VK_EXT_pipeline_creation_feedback',        1, True),
     Extension('VK_EXT_sampler_filter_minmax',             1, 'device->rad_info.chip_class >= CIK'),
     Extension('VK_EXT_scalar_block_layout',               1, 'device->rad_info.chip_class >= CIK'),
     Extension('VK_EXT_shader_viewport_index_layer',       1, True),
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 7f2f96c540a..91537db1ac5 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -2034,12 +2034,52 @@ merge_tess_info(struct shader_info *tes_info,
 }
 
 static
+void radv_init_feedback(const VkPipelineCreationFeedbackCreateInfoEXT *ext)
+{
+	if (!ext)
+		return;
+
+	if (ext->pPipelineCreationFeedback) {
+		ext->pPipelineCreationFeedback->flags = 0;
+		ext->pPipelineCreationFeedback->duration = 0;
+	}
+
+	for (unsigned i = 0; i < ext->pipelineStageCreationFeedbackCount; ++i) {
+		ext->pPipelineStageCreationFeedbacks[i].flags = 0;
+		ext->pPipelineStageCreationFeedbacks[i].duration = 0;
+	}
+}
+
+static
+void radv_start_feedback(VkPipelineCreationFeedbackEXT *feedback)
+{
+	if (!feedback)
+		return;
+
+	feedback->duration -= radv_get_current_time();
+	feedback ->flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT;
+}
+
+static
+void radv_stop_feedback(VkPipelineCreationFeedbackEXT *feedback, bool cache_hit)
+{
+	if (!feedback)
+		return;
+
+	feedback->duration += radv_get_current_time();
+	feedback ->flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT |
+	                   (cache_hit ? VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT : 0);
+}
+
+static
 void radv_create_shaders(struct radv_pipeline *pipeline,
                          struct radv_device *device,
                          struct radv_pipeline_cache *cache,
                          const struct radv_pipeline_key *key,
                          const VkPipelineShaderStageCreateInfo **pStages,
-                         const VkPipelineCreateFlags flags)
+                         const VkPipelineCreateFlags flags,
+                         VkPipelineCreationFeedbackEXT *pipeline_feedback,
+                         VkPipelineCreationFeedbackEXT **stage_feedbacks)
 {
 	struct radv_shader_module fs_m = {0};
 	struct radv_shader_module *modules[MESA_SHADER_STAGES] = { 0, };
@@ -2049,6 +2089,8 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 	struct radv_shader_variant_key keys[MESA_SHADER_STAGES] = {{{{0}}}};
 	unsigned char hash[20], gs_copy_hash[20];
 
+	radv_start_feedback(pipeline_feedback);
+
 	for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
 		if (pStages[i]) {
 			modules[i] = radv_shader_module_from_handle(pStages[i]->module);
@@ -2065,14 +2107,18 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 	memcpy(gs_copy_hash, hash, 20);
 	gs_copy_hash[0] ^= 1;
 
+	bool found_in_application_cache = true;
 	if (modules[MESA_SHADER_GEOMETRY]) {
 		struct radv_shader_variant *variants[MESA_SHADER_STAGES] = {0};
-		radv_create_shader_variants_from_pipeline_cache(device, cache, gs_copy_hash, variants);
+		radv_create_shader_variants_from_pipeline_cache(device, cache, gs_copy_hash, variants,
+		                                                &found_in_application_cache);
 		pipeline->gs_copy_shader = variants[MESA_SHADER_GEOMETRY];
 	}
 
-	if (radv_create_shader_variants_from_pipeline_cache(device, cache, hash, pipeline->shaders) &&
+	if (radv_create_shader_variants_from_pipeline_cache(device, cache, hash, pipeline->shaders,
+	                                                    &found_in_application_cache) &&
 	    (!modules[MESA_SHADER_GEOMETRY] || pipeline->gs_copy_shader)) {
+		radv_stop_feedback(pipeline_feedback, found_in_application_cache);
 		return;
 	}
 
@@ -2090,6 +2136,8 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 		if (!modules[i])
 			continue;
 
+		radv_start_feedback(stage_feedbacks[i]);
+
 		nir[i] = radv_shader_compile_to_nir(device, modules[i],
 						    stage ? stage->pName : "main", i,
 						    stage ? stage->pSpecializationInfo : NULL,
@@ -2101,6 +2149,8 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 		if (nir[i]->info.name) {
 			nir[i] = nir_shader_clone(NULL, nir[i]);
 		}
+
+		radv_stop_feedback(stage_feedbacks[i], false);
 	}
 
 	if (nir[MESA_SHADER_TESS_CTRL]) {
@@ -2124,10 +2174,14 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 
 	if (nir[MESA_SHADER_FRAGMENT]) {
 		if (!pipeline->shaders[MESA_SHADER_FRAGMENT]) {
+			radv_start_feedback(stage_feedbacks[MESA_SHADER_FRAGMENT]);
+
 			pipeline->shaders[MESA_SHADER_FRAGMENT] =
 			       radv_shader_variant_create(device, modules[MESA_SHADER_FRAGMENT], &nir[MESA_SHADER_FRAGMENT], 1,
 			                                  pipeline->layout, keys + MESA_SHADER_FRAGMENT,
 			                                  &codes[MESA_SHADER_FRAGMENT], &code_sizes[MESA_SHADER_FRAGMENT]);
+
+			radv_stop_feedback(stage_feedbacks[MESA_SHADER_FRAGMENT], false);
 		}
 
 		/* TODO: These are no longer used as keys we should refactor this */
@@ -2146,10 +2200,15 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 			struct nir_shader *combined_nir[] = {nir[MESA_SHADER_VERTEX], nir[MESA_SHADER_TESS_CTRL]};
 			struct radv_shader_variant_key key = keys[MESA_SHADER_TESS_CTRL];
 			key.tcs.vs_key = keys[MESA_SHADER_VERTEX].vs;
+
+			radv_start_feedback(stage_feedbacks[MESA_SHADER_TESS_CTRL]);
+
 			pipeline->shaders[MESA_SHADER_TESS_CTRL] = radv_shader_variant_create(device, modules[MESA_SHADER_TESS_CTRL], combined_nir, 2,
 			                                                                      pipeline->layout,
 			                                                                      &key, &codes[MESA_SHADER_TESS_CTRL],
 			                                                                      &code_sizes[MESA_SHADER_TESS_CTRL]);
+
+			radv_stop_feedback(stage_feedbacks[MESA_SHADER_TESS_CTRL], false);
 		}
 		modules[MESA_SHADER_VERTEX] = NULL;
 		keys[MESA_SHADER_TESS_EVAL].tes.num_patches = pipeline->shaders[MESA_SHADER_TESS_CTRL]->info.tcs.num_patches;
@@ -2160,10 +2219,15 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 		gl_shader_stage pre_stage = modules[MESA_SHADER_TESS_EVAL] ? MESA_SHADER_TESS_EVAL : MESA_SHADER_VERTEX;
 		if (!pipeline->shaders[MESA_SHADER_GEOMETRY]) {
 			struct nir_shader *combined_nir[] = {nir[pre_stage], nir[MESA_SHADER_GEOMETRY]};
+
+			radv_start_feedback(stage_feedbacks[MESA_SHADER_GEOMETRY]);
+
 			pipeline->shaders[MESA_SHADER_GEOMETRY] = radv_shader_variant_create(device, modules[MESA_SHADER_GEOMETRY], combined_nir, 2,
 			                                                                     pipeline->layout,
 			                                                                     &keys[pre_stage] , &codes[MESA_SHADER_GEOMETRY],
 		                                                                     &code_sizes[MESA_SHADER_GEOMETRY]);
+
+			radv_stop_feedback(stage_feedbacks[MESA_SHADER_GEOMETRY], false);
 		}
 		modules[pre_stage] = NULL;
 	}
@@ -2177,10 +2241,15 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 				keys[MESA_SHADER_TESS_EVAL].tes.num_patches = pipeline->shaders[MESA_SHADER_TESS_CTRL]->info.tcs.num_patches;
 				keys[MESA_SHADER_TESS_EVAL].tes.tcs_num_outputs = util_last_bit64(pipeline->shaders[MESA_SHADER_TESS_CTRL]->info.info.tcs.outputs_written);
 			}
+
+			radv_start_feedback(stage_feedbacks[i]);
+
 			pipeline->shaders[i] = radv_shader_variant_create(device, modules[i], &nir[i], 1,
 									  pipeline->layout,
 									  keys + i, &codes[i],
 									  &code_sizes[i]);
+
+			radv_stop_feedback(stage_feedbacks[i], false);
 		}
 	}
 
@@ -2230,6 +2299,8 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 
 	if (fs_m.nir)
 		ralloc_free(fs_m.nir);
+
+	radv_stop_feedback(pipeline_feedback, false);
 }
 
 static uint32_t
@@ -3591,14 +3662,23 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
 
 	struct radv_blend_state blend = radv_pipeline_init_blend_state(pipeline, pCreateInfo, extra);
 
+	const VkPipelineCreationFeedbackCreateInfoEXT *creation_feedback =
+		vk_find_struct_const(pCreateInfo->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT);
+	radv_init_feedback(creation_feedback);
+
+	VkPipelineCreationFeedbackEXT *pipeline_feedback = creation_feedback ? creation_feedback->pPipelineCreationFeedback : NULL;
+
 	const VkPipelineShaderStageCreateInfo *pStages[MESA_SHADER_STAGES] = { 0, };
+	VkPipelineCreationFeedbackEXT *stage_feedbacks[MESA_SHADER_STAGES];
 	for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
 		gl_shader_stage stage = ffs(pCreateInfo->pStages[i].stage) - 1;
 		pStages[stage] = &pCreateInfo->pStages[i];
+		if(creation_feedback)
+			stage_feedbacks[stage] = &creation_feedback->pPipelineStageCreationFeedbacks[i];
 	}
 
 	struct radv_pipeline_key key = radv_generate_graphics_pipeline_key(pipeline, pCreateInfo, &blend, has_view_index);
-	radv_create_shaders(pipeline, device, cache, &key, pStages, pCreateInfo->flags);
+	radv_create_shaders(pipeline, device, cache, &key, pStages, pCreateInfo->flags, pipeline_feedback, stage_feedbacks);
 
 	pipeline->graphics.spi_baryc_cntl = S_0286E0_FRONT_FACE_ALL_BITS(1);
 	radv_pipeline_init_multisample_state(pipeline, &blend, pCreateInfo);
@@ -3821,6 +3901,7 @@ static VkResult radv_compute_pipeline_create(
 	RADV_FROM_HANDLE(radv_device, device, _device);
 	RADV_FROM_HANDLE(radv_pipeline_cache, cache, _cache);
 	const VkPipelineShaderStageCreateInfo *pStages[MESA_SHADER_STAGES] = { 0, };
+	VkPipelineCreationFeedbackEXT *stage_feedbacks[MESA_SHADER_STAGES];
 	struct radv_pipeline *pipeline;
 	VkResult result;
 
@@ -3833,8 +3914,16 @@ static VkResult radv_compute_pipeline_create(
 	pipeline->layout = radv_pipeline_layout_from_handle(pCreateInfo->layout);
 	assert(pipeline->layout);
 
+	const VkPipelineCreationFeedbackCreateInfoEXT *creation_feedback =
+		vk_find_struct_const(pCreateInfo->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT);
+	radv_init_feedback(creation_feedback);
+
+	VkPipelineCreationFeedbackEXT *pipeline_feedback = creation_feedback ? creation_feedback->pPipelineCreationFeedback : NULL;
+	if (creation_feedback)
+		stage_feedbacks[MESA_SHADER_COMPUTE] = &creation_feedback->pPipelineStageCreationFeedbacks[0];
+
 	pStages[MESA_SHADER_COMPUTE] = &pCreateInfo->stage;
-	radv_create_shaders(pipeline, device, cache, &(struct radv_pipeline_key) {0}, pStages, pCreateInfo->flags);
+	radv_create_shaders(pipeline, device, cache, &(struct radv_pipeline_key) {0}, pStages, pCreateInfo->flags, pipeline_feedback, stage_feedbacks);
 
 	pipeline->user_data_0[MESA_SHADER_COMPUTE] = radv_pipeline_stage_to_user_data_0(pipeline, MESA_SHADER_COMPUTE, device->physical_device->rad_info.chip_class);
 	pipeline->need_indirect_descriptor_sets |= pipeline->shaders[MESA_SHADER_COMPUTE]->info.need_indirect_descriptor_sets;
diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c
index 9f01191a2f6..57d52610306 100644
--- a/src/amd/vulkan/radv_pipeline_cache.c
+++ b/src/amd/vulkan/radv_pipeline_cache.c
@@ -255,18 +255,23 @@ bool
 radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
 					        struct radv_pipeline_cache *cache,
 					        const unsigned char *sha1,
-					        struct radv_shader_variant **variants)
+					        struct radv_shader_variant **variants,
+						bool *found_in_application_cache)
 {
 	struct cache_entry *entry;
 
-	if (!cache)
+	if (!cache) {
 		cache = device->mem_cache;
+		*found_in_application_cache = false;
+	}
 
 	pthread_mutex_lock(&cache->mutex);
 
 	entry = radv_pipeline_cache_search_unlocked(cache, sha1);
 
 	if (!entry) {
+		*found_in_application_cache = false;
+
 		/* Don't cache when we want debug info, since this isn't
 		 * present in the cache.
 		 */
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 39fa6110fde..82ab4eff8ca 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -396,7 +396,8 @@ bool
 radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
 					        struct radv_pipeline_cache *cache,
 					        const unsigned char *sha1,
-					        struct radv_shader_variant **variants);
+					        struct radv_shader_variant **variants,
+						bool *found_in_application_cache);
 
 void
 radv_pipeline_cache_insert_shaders(struct radv_device *device,
@@ -1961,6 +1962,8 @@ void radv_nir_shader_info_init(struct radv_shader_info *info);
 
 struct radeon_winsys_sem;
 
+uint64_t radv_get_current_time(void);
+
 #define RADV_DEFINE_HANDLE_CASTS(__radv_type, __VkType)		\
 								\
 	static inline struct __radv_type *			\




More information about the mesa-commit mailing list