On Sun, Oct 15, 2017 at 1:36 AM, Timothy Arceri <[email protected]> wrote: > From: Bas Nieuwenhuizen <[email protected]> > > 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 <[email protected]> > --- > 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);
I think this needs to move to an earlier patch. > } > 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 > [email protected] > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
