diff --git a/src/microsoft/compiler/dxil_function.c b/src/microsoft/compiler/dxil_function.c index 18507378400..a6d192a1d7d 100644 --- a/src/microsoft/compiler/dxil_function.c +++ b/src/microsoft/compiler/dxil_function.c @@ -80,6 +80,7 @@ static struct predefined_func_descr predefined_funcs[] = { {"dx.op.evalSnapped", "O", "iiicii", DXIL_ATTR_KIND_READ_NONE}, {"dx.op.evalCentroid", "O", "iiic", DXIL_ATTR_KIND_READ_NONE}, {"dx.op.evalSampleIndex", "O", "iiici", DXIL_ATTR_KIND_READ_NONE}, +{"dx.op.coverage", "i", "i", DXIL_ATTR_KIND_READ_NONE}, }; struct func_descr { diff --git a/src/microsoft/compiler/dxil_signature.c b/src/microsoft/compiler/dxil_signature.c index df2c8794cbb..05df9d2d843 100644 --- a/src/microsoft/compiler/dxil_signature.c +++ b/src/microsoft/compiler/dxil_signature.c @@ -505,11 +505,6 @@ get_input_signature_group(struct dxil_module *mod, const struct dxil_mdnode **in mod->num_psv_inputs = MAX2(mod->num_psv_inputs, semantic.start_row + semantic.rows); - mod->info.has_per_sample_input |= - semantic.kind == DXIL_SEM_SAMPLE_INDEX || - semantic.interpolation == DXIL_INTERP_LINEAR_SAMPLE || - semantic.interpolation == DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE; - ++num_inputs; assert(num_inputs < VARYING_SLOT_MAX); } diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index f2e5a2f9dd6..494544cd0d0 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -264,6 +264,7 @@ enum dxil_intr { DXIL_INTR_EVAL_CENTROID = 89, DXIL_INTR_SAMPLE_INDEX = 90, + DXIL_INTR_COVERAGE = 91, DXIL_INTR_THREAD_ID = 93, DXIL_INTR_GROUP_ID = 94, @@ -2463,10 +2464,10 @@ emit_load_local_workgroup_id(struct ntd_context *ctx, return true; } -static bool -emit_load_unary_external_function(struct ntd_context *ctx, - nir_intrinsic_instr *intr, const char *name, - int32_t dxil_intr) +static const struct dxil_value * +call_unary_external_function(struct ntd_context *ctx, + const char *name, + int32_t dxil_intr) { const struct dxil_func *func = dxil_get_function(&ctx->mod, name, DXIL_I32); @@ -2480,13 +2481,38 @@ emit_load_unary_external_function(struct ntd_context *ctx, const struct dxil_value *args[] = {opcode}; - const struct dxil_value *value = - dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args)); + return dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args)); +} + +static bool +emit_load_unary_external_function(struct ntd_context *ctx, + nir_intrinsic_instr *intr, const char *name, + int32_t dxil_intr) +{ + const struct dxil_value *value = call_unary_external_function(ctx, name, dxil_intr); store_dest_value(ctx, &intr->dest, 0, value); return true; } +static bool +emit_load_sample_mask_in(struct ntd_context *ctx, nir_intrinsic_instr *intr) +{ + const struct dxil_value *value = call_unary_external_function(ctx, + "dx.op.coverage", DXIL_INTR_COVERAGE); + + /* Mask coverage with (1 << sample index). Note, done as an AND to handle extrapolation cases. */ + if (ctx->mod.info.has_per_sample_input) { + value = dxil_emit_binop(&ctx->mod, DXIL_BINOP_AND, value, + dxil_emit_binop(&ctx->mod, DXIL_BINOP_SHL, + dxil_module_get_int32_const(&ctx->mod, 1), + call_unary_external_function(ctx, "dx.op.sampleIndex", DXIL_INTR_SAMPLE_INDEX), 0), 0); + } + + store_dest_value(ctx, &intr->dest, 0, value); + return true; +} + static const struct dxil_value * get_int32_undef(struct dxil_module *m) { @@ -3734,6 +3760,8 @@ emit_intrinsic(struct ntd_context *ctx, nir_intrinsic_instr *intr) case nir_intrinsic_load_sample_id: return emit_load_unary_external_function(ctx, intr, "dx.op.sampleIndex", DXIL_INTR_SAMPLE_INDEX); + case nir_intrinsic_load_sample_mask_in: + return emit_load_sample_mask_in(ctx, intr); case nir_intrinsic_load_shared_dxil: return emit_load_shared(ctx, intr); case nir_intrinsic_load_scratch_dxil: @@ -4846,6 +4874,17 @@ emit_module(struct ntd_context *ctx, const struct nir_to_dxil_options *opts) return false; } + ctx->mod.info.has_per_sample_input = + BITSET_TEST(ctx->shader->info.system_values_read, SYSTEM_VALUE_SAMPLE_ID); + if (!ctx->mod.info.has_per_sample_input && ctx->shader->info.stage == MESA_SHADER_FRAGMENT) { + nir_foreach_variable_with_modes(var, ctx->shader, nir_var_shader_in | nir_var_system_value) { + if (var->data.sample) { + ctx->mod.info.has_per_sample_input = true; + break; + } + } + } + nir_function_impl *entry = nir_shader_get_entrypoint(ctx->shader); nir_metadata_require(entry, nir_metadata_block_index);