From 6a68170c8360d702a25e59740d04f79a4f8323a7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 20 Jun 2017 13:21:04 +1000 Subject: [PATCH] radv: handle primitive id input into fragment shader with no geom shader Fixes: dEQP-VK.pipeline.framebuffer_attachment.no_attachments dEQP-VK.pipeline.framebuffer_attachment.no_attachments_ms Reviewed-by: Kenneth Graunke Reviewed-by: Bas Nieuwenhuizen Signed-off-by: Dave Airlie --- src/amd/common/ac_nir_to_llvm.c | 26 ++++++++++++++++--- src/amd/common/ac_nir_to_llvm.h | 3 +++ src/amd/vulkan/radv_cmd_buffer.c | 2 +- src/amd/vulkan/radv_pipeline.c | 43 +++++++++++++++++++++++++------- src/amd/vulkan/radv_private.h | 1 + src/amd/vulkan/si_cmd_buffer.c | 3 +++ 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index afef3fd28d4..f0ae7087379 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -5124,6 +5124,7 @@ si_llvm_init_export_args(struct nir_to_llvm_context *ctx, static void handle_vs_outputs_post(struct nir_to_llvm_context *ctx, + bool export_prim_id, struct ac_vs_output_info *outinfo) { uint32_t param_count = 0; @@ -5265,6 +5266,23 @@ handle_vs_outputs_post(struct nir_to_llvm_context *ctx, ac_build_export(&ctx->ac, &pos_args[i]); } + + if (export_prim_id) { + LLVMValueRef values[4]; + target = V_008DFC_SQ_EXP_PARAM + param_count; + outinfo->vs_output_param_offset[VARYING_SLOT_PRIMITIVE_ID] = param_count; + param_count++; + + values[0] = ctx->vs_prim_id; + ctx->shader_info->vs.vgpr_comp_cnt = MAX2(2, + ctx->shader_info->vs.vgpr_comp_cnt); + for (unsigned j = 1; j < 4; j++) + values[j] = ctx->f32zero; + si_llvm_init_export_args(ctx, values, target, &args); + ac_build_export(&ctx->ac, &args); + outinfo->export_prim_id = true; + } + outinfo->pos_exports = num_pos_exports; outinfo->param_exports = param_count; } @@ -5700,7 +5718,8 @@ handle_shader_outputs_post(struct nir_to_llvm_context *ctx) else if (ctx->options->key.vs.as_es) handle_es_outputs_post(ctx, &ctx->shader_info->vs.es_info); else - handle_vs_outputs_post(ctx, &ctx->shader_info->vs.outinfo); + handle_vs_outputs_post(ctx, ctx->options->key.vs.export_prim_id, + &ctx->shader_info->vs.outinfo); break; case MESA_SHADER_FRAGMENT: handle_fs_outputs_post(ctx); @@ -5715,7 +5734,8 @@ handle_shader_outputs_post(struct nir_to_llvm_context *ctx) if (ctx->options->key.tes.as_es) handle_es_outputs_post(ctx, &ctx->shader_info->tes.es_info); else - handle_vs_outputs_post(ctx, &ctx->shader_info->tes.outinfo); + handle_vs_outputs_post(ctx, ctx->options->key.tes.export_prim_id, + &ctx->shader_info->tes.outinfo); break; default: break; @@ -6191,7 +6211,7 @@ ac_gs_copy_shader_emit(struct nir_to_llvm_context *ctx) } idx += slot_inc; } - handle_vs_outputs_post(ctx, &ctx->shader_info->vs.outinfo); + handle_vs_outputs_post(ctx, false, &ctx->shader_info->vs.outinfo); } void ac_create_gs_copy_shader(LLVMTargetMachineRef tm, diff --git a/src/amd/common/ac_nir_to_llvm.h b/src/amd/common/ac_nir_to_llvm.h index 724d5e6b0fd..54d54891ac1 100644 --- a/src/amd/common/ac_nir_to_llvm.h +++ b/src/amd/common/ac_nir_to_llvm.h @@ -41,10 +41,12 @@ struct ac_vs_variant_key { uint32_t instance_rate_inputs; uint32_t as_es:1; uint32_t as_ls:1; + uint32_t export_prim_id:1; }; struct ac_tes_variant_key { uint32_t as_es:1; + uint32_t export_prim_id:1; }; struct ac_tcs_variant_key { @@ -128,6 +130,7 @@ struct ac_vs_output_info { bool writes_pointsize; bool writes_layer; bool writes_viewport_index; + bool export_prim_id; uint32_t export_mask; unsigned pos_exports; }; diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 9f36d982234..105384d315d 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -669,7 +669,7 @@ radv_emit_vertex_shader(struct radv_cmd_buffer *cmd_buffer, else radv_emit_hw_vs(cmd_buffer, pipeline, vs, &vs->info.vs.outinfo); - radeon_set_context_reg(cmd_buffer->cs, R_028A84_VGT_PRIMITIVEID_EN, 0); + radeon_set_context_reg(cmd_buffer->cs, R_028A84_VGT_PRIMITIVEID_EN, pipeline->graphics.vgt_primitiveid_en); } diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index e58ada68cc9..0c262799f0c 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -605,11 +605,14 @@ radv_pipeline_compile(struct radv_pipeline *pipeline, } static union ac_shader_variant_key -radv_compute_tes_key(bool as_es) +radv_compute_tes_key(bool as_es, bool export_prim_id) { union ac_shader_variant_key key; memset(&key, 0, sizeof(key)); key.tes.as_es = as_es; + /* export prim id only happens when no geom shader */ + if (!as_es) + key.tes.export_prim_id = export_prim_id; return key; } @@ -640,10 +643,12 @@ radv_tess_pipeline_compile(struct radv_pipeline *pipeline, 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 tes_key; union ac_shader_variant_key tcs_key; bool dump = (pipeline->device->debug_flags & RADV_DEBUG_DUMP_SHADERS); + tes_key = radv_compute_tes_key(radv_pipeline_has_gs(pipeline), + pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input); if (tes_module->nir) _mesa_sha1_compute(tes_module->nir->info.name, strlen(tes_module->nir->info.name), @@ -1606,7 +1611,7 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, } static union ac_shader_variant_key -radv_compute_vs_key(const VkGraphicsPipelineCreateInfo *pCreateInfo, bool as_es, bool as_ls) +radv_compute_vs_key(const VkGraphicsPipelineCreateInfo *pCreateInfo, bool as_es, bool as_ls, bool export_prim_id) { union ac_shader_variant_key key; const VkPipelineVertexInputStateCreateInfo *input_state = @@ -1616,6 +1621,7 @@ radv_compute_vs_key(const VkGraphicsPipelineCreateInfo *pCreateInfo, bool as_es, key.vs.instance_rate_inputs = 0; key.vs.as_es = as_es; key.vs.as_ls = as_ls; + key.vs.export_prim_id = export_prim_id; for (unsigned i = 0; i < input_state->vertexAttributeDescriptionCount; ++i) { unsigned binding; @@ -1857,6 +1863,24 @@ static uint32_t si_vgt_gs_mode(struct radv_shader_variant *gs) S_028A40_GS_WRITE_OPTIMIZE(1); } +static void calculate_vgt_gs_mode(struct radv_pipeline *pipeline) +{ + struct radv_shader_variant *vs; + vs = radv_pipeline_has_gs(pipeline) ? pipeline->gs_copy_shader : (radv_pipeline_has_tess(pipeline) ? pipeline->shaders[MESA_SHADER_TESS_EVAL] : pipeline->shaders[MESA_SHADER_VERTEX]); + + struct ac_vs_output_info *outinfo = &vs->info.vs.outinfo; + + pipeline->graphics.vgt_primitiveid_en = false; + pipeline->graphics.vgt_gs_mode = 0; + + if (radv_pipeline_has_gs(pipeline)) { + pipeline->graphics.vgt_gs_mode = si_vgt_gs_mode(pipeline->shaders[MESA_SHADER_GEOMETRY]); + } else if (outinfo->export_prim_id) { + pipeline->graphics.vgt_gs_mode = S_028A40_MODE(V_028A40_GS_SCENARIO_A); + pipeline->graphics.vgt_primitiveid_en = true; + } +} + static void calculate_pa_cl_vs_out_cntl(struct radv_pipeline *pipeline) { struct radv_shader_variant *vs; @@ -2018,11 +2042,14 @@ radv_pipeline_init(struct radv_pipeline *pipeline, if (modules[MESA_SHADER_VERTEX]) { bool as_es = false; bool as_ls = false; + bool export_prim_id = false; if (modules[MESA_SHADER_TESS_CTRL]) as_ls = true; else if (modules[MESA_SHADER_GEOMETRY]) as_es = true; - union ac_shader_variant_key key = radv_compute_vs_key(pCreateInfo, as_es, as_ls); + else if (pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input) + export_prim_id = true; + union ac_shader_variant_key key = radv_compute_vs_key(pCreateInfo, as_es, as_ls, export_prim_id); pipeline->shaders[MESA_SHADER_VERTEX] = radv_pipeline_compile(pipeline, cache, modules[MESA_SHADER_VERTEX], @@ -2035,7 +2062,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, } if (modules[MESA_SHADER_GEOMETRY]) { - union ac_shader_variant_key key = radv_compute_vs_key(pCreateInfo, false, false); + union ac_shader_variant_key key = radv_compute_vs_key(pCreateInfo, false, false, false); pipeline->shaders[MESA_SHADER_GEOMETRY] = radv_pipeline_compile(pipeline, cache, modules[MESA_SHADER_GEOMETRY], @@ -2045,10 +2072,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, pipeline->layout, &key); pipeline->active_stages |= mesa_to_vk_shader_stage(MESA_SHADER_GEOMETRY); - - pipeline->graphics.vgt_gs_mode = si_vgt_gs_mode(pipeline->shaders[MESA_SHADER_GEOMETRY]); - } else - pipeline->graphics.vgt_gs_mode = 0; + } if (modules[MESA_SHADER_TESS_EVAL]) { assert(modules[MESA_SHADER_TESS_CTRL]); @@ -2130,6 +2154,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, ps->info.fs.writes_z ? V_028710_SPI_SHADER_32_R : V_028710_SPI_SHADER_ZERO; + calculate_vgt_gs_mode(pipeline); calculate_pa_cl_vs_out_cntl(pipeline); calculate_ps_inputs(pipeline); diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 87cb0a67fe7..630448d3b2a 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1071,6 +1071,7 @@ struct radv_pipeline { unsigned prim; unsigned gs_out; uint32_t vgt_gs_mode; + bool vgt_primitiveid_en; bool prim_restart_enable; unsigned esgs_ring_size; unsigned gsvs_ring_size; diff --git a/src/amd/vulkan/si_cmd_buffer.c b/src/amd/vulkan/si_cmd_buffer.c index 86e8e3e4986..bf08214c551 100644 --- a/src/amd/vulkan/si_cmd_buffer.c +++ b/src/amd/vulkan/si_cmd_buffer.c @@ -700,6 +700,9 @@ si_get_ia_multi_vgt_param(struct radv_cmd_buffer *cmd_buffer, multi_instances_smaller_than_primgroup = indirect_draw || (instanced_draw && num_prims < primgroup_size); + if (cmd_buffer->state.pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input) + ia_switch_on_eoi = true; + if (radv_pipeline_has_tess(cmd_buffer->state.pipeline)) { /* SWITCH_ON_EOI must be set if PrimID is used. */ if (cmd_buffer->state.pipeline->shaders[MESA_SHADER_TESS_CTRL]->info.tcs.uses_prim_id || -- 2.30.2