From b09e690f3b77accfe62398ed314b6ddb0303bf7b Mon Sep 17 00:00:00 2001 From: Brian Ho Date: Fri, 24 Apr 2020 08:05:48 -0700 Subject: [PATCH] turnip: Lower shaders for tessellation To enable lowering of tess-related shaders, this commit sets the tessellation primitive field of the ir3_shader_key. In addition, this commit sets various tessellation flags for spirv_to_nir configuration. Part-of: --- src/freedreno/vulkan/tu_pipeline.c | 29 ++++++++++++++++++++++++++++- src/freedreno/vulkan/tu_shader.c | 10 +++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index ef1422fa708..6093881217e 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -1672,7 +1672,26 @@ tu_pipeline_shader_key_init(struct ir3_shader_key *key, if (msaa_info->sampleShadingEnable) key->sample_shading = true; - /* TODO: Populate the remaining fields of ir3_shader_key. */ + /* We set this after we compile to NIR because we need the prim mode */ + key->tessellation = IR3_TESS_NONE; +} + +static uint32_t +tu6_get_tessmode(struct tu_shader* shader) +{ + uint32_t primitive_mode = shader->ir3_shader->nir->info.tess.primitive_mode; + switch (primitive_mode) { + case GL_ISOLINES: + return IR3_TESS_ISOLINES; + case GL_TRIANGLES: + return IR3_TESS_TRIANGLES; + case GL_QUADS: + return IR3_TESS_QUADS; + case GL_NONE: + return IR3_TESS_NONE; + default: + unreachable("bad tessmode"); + } } static VkResult @@ -1702,6 +1721,14 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder) if (!shader) return VK_ERROR_OUT_OF_HOST_MEMORY; + /* In SPIR-V generated from GLSL, the primitive mode is specified in the + * tessellation evaluation shader, but in SPIR-V generated from HLSL, + * the mode is specified in the tessellation control shader. */ + if ((stage == MESA_SHADER_TESS_EVAL || stage == MESA_SHADER_TESS_CTRL) && + key.tessellation == IR3_TESS_NONE) { + key.tessellation = tu6_get_tessmode(shader); + } + builder->shaders[stage] = shader; } diff --git a/src/freedreno/vulkan/tu_shader.c b/src/freedreno/vulkan/tu_shader.c index 1a0772726f5..b25a959b89e 100644 --- a/src/freedreno/vulkan/tu_shader.c +++ b/src/freedreno/vulkan/tu_shader.c @@ -43,8 +43,11 @@ tu_spirv_to_nir(struct ir3_compiler *compiler, const struct spirv_to_nir_options spirv_options = { .frag_coord_is_sysval = true, .lower_ubo_ssbo_access_to_offsets = true, + .tess_levels_are_sysvals = true, + .lower_tess_levels_to_vec = true, .caps = { - .transform_feedback = compiler->gpu_id >= 600, + .transform_feedback = true, + .tessellation = true, }, }; const nir_shader_compiler_options *nir_options = @@ -608,6 +611,11 @@ tu_shader_create(struct tu_device *dev, NIR_PASS_V(nir, nir_opt_combine_stores, nir_var_all); /* ir3 doesn't support indirect input/output */ + /* TODO: We shouldn't perform this lowering pass on gl_TessLevelInner + * and gl_TessLevelOuter. Since the tess levels are actually stored in + * a global BO, they can be directly accessed via stg and ldg. + * nir_lower_indirect_derefs will instead generate a big if-ladder which + * isn't *incorrect* but is much less efficient. */ NIR_PASS_V(nir, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out); NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false); -- 2.30.2