[Mesa-dev] [PATCH 5/9] radv: add radv_create_shaders() helper
Timothy Arceri
tarceri at itsqueeze.com
Sat Oct 14 23:36:43 UTC 2017
From: Bas Nieuwenhuizen <basni at google.com>
This is a combined shader creation helper than will help us to
create the shaders for each stage at once. This will allow us to
do some link time optimisations.
Signed-off-by: Timothy Arceri <tarceri at itsqueeze.com>
---
src/amd/vulkan/radv_pipeline.c | 130 +++++++++++++++++++++++++++++++++++
src/amd/vulkan/radv_pipeline_cache.c | 3 +-
2 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 415a6cd62b..f923027036 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -1736,20 +1736,150 @@ static void calculate_ps_inputs(struct radv_pipeline *pipeline)
flat_shade = !!(ps->info.fs.flat_shaded_mask & (1u << ps_offset));
pipeline->graphics.ps_input_cntl[ps_offset] = offset_to_ps_input(vs_offset, flat_shade);
++ps_offset;
}
pipeline->graphics.ps_input_cntl_num = ps_offset;
}
+static
+void radv_create_shaders(struct radv_pipeline *pipeline,
+ struct radv_device *device,
+ struct radv_pipeline_cache *cache,
+ struct ac_shader_variant_key *keys,
+ const VkPipelineShaderStageCreateInfo **pStages)
+{
+ struct radv_shader_module fs_m = {0};
+ struct radv_shader_module *modules[MESA_SHADER_STAGES] = { 0, };
+ nir_shader *nir[MESA_SHADER_STAGES] = {0};
+ void *codes[MESA_SHADER_STAGES] = {0};
+ unsigned code_sizes[MESA_SHADER_STAGES] = {0};
+ unsigned char hash[20], gs_copy_hash[20];
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
+ if (pStages[i]) {
+ modules[i] = radv_shader_module_from_handle(pStages[i]->module);
+ if (modules[i]->nir)
+ _mesa_sha1_compute(modules[i]->nir->info.name,
+ strlen(modules[i]->nir->info.name),
+ modules[i]->sha1);
+ }
+ }
+
+ radv_hash_shaders(hash, pStages, pipeline->layout, keys, get_hash_flags(device));
+ memcpy(gs_copy_hash, hash, 20);
+ gs_copy_hash[0] ^= 1;
+
+ if (modules[MESA_SHADER_GEOMETRY]) {
+ pipeline->gs_copy_shader =
+ radv_create_shader_variant_from_pipeline_cache(
+ pipeline->device,
+ cache,
+ gs_copy_hash);
+ }
+
+ if (radv_create_shader_variants_from_pipeline_cache(device, cache, hash, pipeline->shaders) &&
+ (!modules[MESA_SHADER_GEOMETRY] || pipeline->gs_copy_shader))
+ return;
+
+ if (!modules[MESA_SHADER_FRAGMENT]) {
+ nir_builder fs_b;
+ nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
+ fs_b.shader->info.name = ralloc_strdup(fs_b.shader, "noop_fs");
+ fs_m.nir = fs_b.shader;
+ modules[MESA_SHADER_FRAGMENT] = &fs_m;
+ }
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
+ const VkPipelineShaderStageCreateInfo *stage = pStages[i];
+
+ if (!modules[i])
+ continue;
+
+ nir[i] = radv_shader_compile_to_nir(device, modules[i],
+ stage ? stage->pName : "main", i,
+ stage ? stage->pSpecializationInfo : NULL);
+ pipeline->active_stages |= mesa_to_vk_shader_stage(i);
+ }
+
+ if (nir[MESA_SHADER_TESS_CTRL]) {
+ /* TODO: This is no longer used as a key we should refactor this */
+ if (keys)
+ keys[MESA_SHADER_TESS_CTRL].tcs.primitive_mode = nir[MESA_SHADER_TESS_EVAL]->info.tess.primitive_mode;
+
+ nir_lower_tes_patch_vertices(nir[MESA_SHADER_TESS_EVAL], nir[MESA_SHADER_TESS_CTRL]->info.tess.tcs_vertices_out);
+ }
+
+ if (nir[MESA_SHADER_FRAGMENT]) {
+ pipeline->shaders[MESA_SHADER_FRAGMENT] =
+ radv_shader_variant_create(device, modules[MESA_SHADER_FRAGMENT], nir[MESA_SHADER_FRAGMENT],
+ pipeline->layout, keys ? keys + MESA_SHADER_FRAGMENT : 0,
+ &codes[MESA_SHADER_FRAGMENT], &code_sizes[MESA_SHADER_FRAGMENT]);
+
+ /* TODO: These are no longer used as keys we should refactor this */
+ if (keys) {
+ keys[MESA_SHADER_VERTEX].vs.export_prim_id =
+ pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input;
+ keys[MESA_SHADER_TESS_EVAL].tes.export_prim_id =
+ pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input;
+ }
+
+ pipeline->active_stages |= mesa_to_vk_shader_stage(MESA_SHADER_FRAGMENT);
+ }
+
+ for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+ if(modules[i] && !pipeline->shaders[i]) {
+ pipeline->shaders[i] = radv_shader_variant_create(device, modules[i], nir[i],
+ pipeline->layout,
+ keys ? keys + i : 0, &codes[i],
+ &code_sizes[i]);
+
+ pipeline->active_stages |= mesa_to_vk_shader_stage(i);
+ }
+ }
+
+ if(modules[MESA_SHADER_GEOMETRY]) {
+ void *gs_copy_code = NULL;
+ unsigned gs_copy_code_size = 0;
+ if (!pipeline->gs_copy_shader) {
+ pipeline->gs_copy_shader = radv_create_gs_copy_shader(
+ device, nir[MESA_SHADER_GEOMETRY], &gs_copy_code,
+ &gs_copy_code_size,
+ keys[MESA_SHADER_GEOMETRY].has_multiview_view_index);
+ }
+
+ if (pipeline->gs_copy_shader) {
+ pipeline->gs_copy_shader =
+ radv_pipeline_cache_insert_shader(device, cache,
+ gs_copy_hash,
+ pipeline->gs_copy_shader,
+ gs_copy_code,
+ gs_copy_code_size);
+ }
+ free(gs_copy_code);
+ }
+
+ radv_pipeline_cache_insert_shaders(device, cache, hash, pipeline->shaders,
+ (const void**)codes, code_sizes);
+
+ for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+ free(codes[i]);
+ if (modules[i] && !modules[i]->nir)
+ ralloc_free(nir[i]);
+ }
+
+ if (fs_m.nir)
+ ralloc_free(fs_m.nir);
+}
+
static VkResult
radv_pipeline_init(struct radv_pipeline *pipeline,
struct radv_device *device,
struct radv_pipeline_cache *cache,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct radv_graphics_pipeline_create_info *extra,
const VkAllocationCallbacks *alloc)
{
struct radv_shader_module fs_m = {0};
VkResult result;
diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c
index feffb4e77b..7924be0c90 100644
--- a/src/amd/vulkan/radv_pipeline_cache.c
+++ b/src/amd/vulkan/radv_pipeline_cache.c
@@ -470,21 +470,22 @@ radv_pipeline_cache_insert_shaders(struct radv_device *device,
pthread_mutex_lock(&cache->mutex);
struct cache_entry *entry = radv_pipeline_cache_search_unlocked(cache, sha1);
if (entry) {
for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
if (entry->variants[i]) {
radv_shader_variant_destroy(cache->device, variants[i]);
variants[i] = entry->variants[i];
} else {
entry->variants[i] = variants[i];
}
- p_atomic_inc(&variants[i]->ref_count);
+ if (variants[i])
+ p_atomic_inc(&variants[i]->ref_count);
}
pthread_mutex_unlock(&cache->mutex);
return;
}
size_t size = sizeof(*entry);
for (int i = 0; i < MESA_SHADER_STAGES; ++i)
if (variants[i])
size += sizeof(struct cache_entry_variant_info) + code_sizes[i];
--
2.13.6
More information about the mesa-dev
mailing list