ctx->gs_wave_id = ac_unpack_param(&ctx->ac, ctx->merged_wave_info, 16, 8);
 }
 
+/* Ensure that the esgs ring is declared.
+ *
+ * We declare it with 64KB alignment as a hint that the
+ * pointer value will always be 0.
+ */
+static void declare_esgs_ring(struct radv_shader_context *ctx)
+{
+       if (ctx->esgs_ring)
+               return;
+
+       assert(!LLVMGetNamedGlobal(ctx->ac.module, "esgs_ring"));
+
+       ctx->esgs_ring = LLVMAddGlobalInAddressSpace(
+               ctx->ac.module, LLVMArrayType(ctx->ac.i32, 0),
+               "esgs_ring",
+               AC_ADDR_SPACE_LDS);
+       LLVMSetLinkage(ctx->esgs_ring, LLVMExternalLinkage);
+       LLVMSetAlignment(ctx->esgs_ring, 64 * 1024);
+}
 
 static
 LLVMModuleRef ac_translate_nir_to_llvm(struct ac_llvm_compiler *ac_llvm,
                        ctx.abi.emit_kill = radv_emit_kill;
                }
 
+               if (shaders[i]->info.stage == MESA_SHADER_VERTEX &&
+                   ctx.options->key.vs_common_out.as_ngg &&
+                   ctx.options->key.vs_common_out.export_prim_id) {
+                       declare_esgs_ring(&ctx);
+               }
+
                if (i)
                        ac_emit_barrier(&ctx.ac, ctx.stage);