From: Bas Nieuwenhuizen <ba...@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 <tarc...@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

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to