aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2017-03-30 08:45:42 +0100
committerDave Airlie <[email protected]>2017-04-01 07:16:51 +1000
commit60fc0544e085bae1d19fa75f9d7806de50c38cef (patch)
tree28414bb692937604b6d59221f965fa667febe7b6
parentaaabdd6bc6ac6e7edf218c473cf2a7a9a02c116e (diff)
radv/pipeline: handle tessellation shader compilation
So tess shaders have some circular dependencies, TCS needs the TES primitive mode TES needs the TCS vertices out This builds the nir for each shader first to get the info, executes a tes specific nir pass, then builds the LLVM shaders. Reviewed-by: Bas Nieuwenhuizen <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
-rw-r--r--src/amd/vulkan/radv_pipeline.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index fdf6f87fac7..c2dd498b078 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -589,6 +589,131 @@ radv_pipeline_compile(struct radv_pipeline *pipeline,
return variant;
}
+static union ac_shader_variant_key
+radv_compute_tes_key(bool as_es)
+{
+ union ac_shader_variant_key key;
+ memset(&key, 0, sizeof(key));
+ key.tes.as_es = as_es;
+ return key;
+}
+
+static union ac_shader_variant_key
+radv_compute_tcs_key(unsigned primitive_mode, unsigned input_vertices)
+{
+ union ac_shader_variant_key key;
+ memset(&key, 0, sizeof(key));
+ key.tcs.primitive_mode = primitive_mode;
+ key.tcs.input_vertices = input_vertices;
+ return key;
+}
+
+static void
+radv_tess_pipeline_compile(struct radv_pipeline *pipeline,
+ struct radv_pipeline_cache *cache,
+ struct radv_shader_module *tcs_module,
+ struct radv_shader_module *tes_module,
+ const char *tcs_entrypoint,
+ const char *tes_entrypoint,
+ const VkSpecializationInfo *tcs_spec_info,
+ const VkSpecializationInfo *tes_spec_info,
+ struct radv_pipeline_layout *layout,
+ unsigned input_vertices)
+{
+ unsigned char tcs_sha1[20], tes_sha1[20];
+ struct radv_shader_variant *tes_variant = NULL, *tcs_variant = NULL;
+ nir_shader *tes_nir, *tcs_nir;
+ void *tes_code = NULL, *tcs_code = NULL;
+ unsigned tes_code_size = 0, tcs_code_size = 0;
+ union ac_shader_variant_key tes_key = radv_compute_tes_key(radv_pipeline_has_gs(pipeline));
+ union ac_shader_variant_key tcs_key;
+ bool dump = (pipeline->device->debug_flags & RADV_DEBUG_DUMP_SHADERS);
+
+ if (tes_module->nir)
+ _mesa_sha1_compute(tes_module->nir->info->name,
+ strlen(tes_module->nir->info->name),
+ tes_module->sha1);
+ radv_hash_shader(tes_sha1, tes_module, tes_entrypoint, tes_spec_info, layout, &tes_key, 0);
+
+ tes_variant = radv_create_shader_variant_from_pipeline_cache(pipeline->device,
+ cache,
+ tes_sha1);
+
+ if (tes_variant) {
+ tcs_key = radv_compute_tcs_key(tes_variant->info.tes.primitive_mode, input_vertices);
+
+ if (tcs_module->nir)
+ _mesa_sha1_compute(tcs_module->nir->info->name,
+ strlen(tcs_module->nir->info->name),
+ tcs_module->sha1);
+
+ radv_hash_shader(tcs_sha1, tcs_module, tcs_entrypoint, tcs_spec_info, layout, &tcs_key, 0);
+
+ tcs_variant = radv_create_shader_variant_from_pipeline_cache(pipeline->device,
+ cache,
+ tcs_sha1);
+ }
+
+ if (tcs_variant && tes_variant) {
+ pipeline->shaders[MESA_SHADER_TESS_CTRL] = tcs_variant;
+ pipeline->shaders[MESA_SHADER_TESS_EVAL] = tes_variant;
+ return;
+ }
+
+ tes_nir = radv_shader_compile_to_nir(pipeline->device,
+ tes_module, tes_entrypoint, MESA_SHADER_TESS_EVAL,
+ tes_spec_info, dump);
+ if (tes_nir == NULL)
+ return;
+
+ tcs_nir = radv_shader_compile_to_nir(pipeline->device,
+ tcs_module, tcs_entrypoint, MESA_SHADER_TESS_CTRL,
+ tcs_spec_info, dump);
+ if (tcs_nir == NULL)
+ return;
+
+ nir_lower_tes_patch_vertices(tes_nir,
+ tcs_nir->info->tess.tcs_vertices_out);
+
+ tes_variant = radv_shader_variant_create(pipeline->device, tes_nir,
+ layout, &tes_key, &tes_code,
+ &tes_code_size, dump);
+
+ tcs_key = radv_compute_tcs_key(tes_nir->info->tess.primitive_mode, input_vertices);
+ if (tcs_module->nir)
+ _mesa_sha1_compute(tcs_module->nir->info->name,
+ strlen(tcs_module->nir->info->name),
+ tcs_module->sha1);
+
+ radv_hash_shader(tcs_sha1, tcs_module, tcs_entrypoint, tcs_spec_info, layout, &tcs_key, 0);
+
+ tcs_variant = radv_shader_variant_create(pipeline->device, tcs_nir,
+ layout, &tcs_key, &tcs_code,
+ &tcs_code_size, dump);
+
+ if (!tes_module->nir)
+ ralloc_free(tes_nir);
+
+ if (!tcs_module->nir)
+ ralloc_free(tcs_nir);
+
+ if (tes_variant)
+ tes_variant = radv_pipeline_cache_insert_shader(cache, tes_sha1, tes_variant,
+ tes_code, tes_code_size);
+
+ if (tcs_variant)
+ tcs_variant = radv_pipeline_cache_insert_shader(cache, tcs_sha1, tcs_variant,
+ tcs_code, tcs_code_size);
+
+ if (tes_code)
+ free(tes_code);
+ if (tcs_code)
+ free(tcs_code);
+ pipeline->shaders[MESA_SHADER_TESS_CTRL] = tcs_variant;
+ pipeline->shaders[MESA_SHADER_TESS_EVAL] = tes_variant;
+ return;
+}
+
static VkResult
radv_pipeline_scratch_init(struct radv_device *device,
struct radv_pipeline *pipeline)
@@ -1876,6 +2001,23 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
} else
pipeline->graphics.vgt_gs_mode = 0;
+ if (modules[MESA_SHADER_TESS_EVAL]) {
+ assert(modules[MESA_SHADER_TESS_CTRL]);
+
+ radv_tess_pipeline_compile(pipeline,
+ cache,
+ modules[MESA_SHADER_TESS_CTRL],
+ modules[MESA_SHADER_TESS_EVAL],
+ pStages[MESA_SHADER_TESS_CTRL]->pName,
+ pStages[MESA_SHADER_TESS_EVAL]->pName,
+ pStages[MESA_SHADER_TESS_CTRL]->pSpecializationInfo,
+ pStages[MESA_SHADER_TESS_EVAL]->pSpecializationInfo,
+ pipeline->layout,
+ pCreateInfo->pTessellationState->patchControlPoints);
+ pipeline->active_stages |= mesa_to_vk_shader_stage(MESA_SHADER_TESS_EVAL) |
+ mesa_to_vk_shader_stage(MESA_SHADER_TESS_CTRL);
+ }
+
if (!modules[MESA_SHADER_FRAGMENT]) {
nir_builder fs_b;
nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);