diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 2a3bd81e314..93ec73760a9 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -107,6 +107,8 @@ struct ntv_context { subgroup_le_mask_var, subgroup_lt_mask_var, subgroup_size_var; + + SpvId discard_func; }; static SpvId @@ -2345,11 +2347,10 @@ emit_load_const(struct ntv_context *ctx, nir_load_const_instr *load_const) static void emit_discard(struct ntv_context *ctx, nir_intrinsic_instr *intr) { - assert(ctx->block_started); - spirv_builder_emit_kill(&ctx->builder); - /* discard is weird in NIR, so let's just create an unreachable block after - it and hope that the vulkan driver will DCE any instructinos in it. */ - spirv_builder_label(&ctx->builder, spirv_builder_new_id(&ctx->builder)); + assert(ctx->discard_func); + SpvId type_void = spirv_builder_type_void(&ctx->builder); + spirv_builder_function_call(&ctx->builder, type_void, + ctx->discard_func, NULL, 0); } static void @@ -4411,6 +4412,19 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, uint32_ spirv_builder_emit_exec_mode(&ctx.builder, entry_point, SpvExecutionModeXfb); } + + if (s->info.stage == MESA_SHADER_FRAGMENT && s->info.fs.uses_discard) { + ctx.discard_func = spirv_builder_new_id(&ctx.builder); + spirv_builder_emit_name(&ctx.builder, ctx.discard_func, "discard"); + spirv_builder_function(&ctx.builder, ctx.discard_func, type_void, + SpvFunctionControlMaskNone, + type_void_func); + SpvId label = spirv_builder_new_id(&ctx.builder); + spirv_builder_label(&ctx.builder, label); + spirv_builder_emit_kill(&ctx.builder); + spirv_builder_function_end(&ctx.builder); + } + spirv_builder_function(&ctx.builder, entry_point, type_void, SpvFunctionControlMaskNone, type_void_func);