microsoft/compiler: Handle input coverage

Note that GL requires input coverage for sample execution mode to
be only the single bit corresponding to the executing sample, so
rearrange things to understand during shader emitting if we're
executing per-sample to emit the right coverage value.

Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14624>
This commit is contained in:
Jesse Natalie 2022-01-14 16:16:31 -08:00 committed by Marge Bot
parent 777a42e309
commit 7748e4799d
3 changed files with 46 additions and 11 deletions

View file

@ -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 {

View file

@ -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);
}

View file

@ -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);