d3d12: Modify shaders when MSAA is disabled

I couldn't find this in a spec but the builtin-gl-sample-mask piglit
seems to expect writing to the output sample mask to do nothing when
max num samples == 0.

The ForcedSampleCount property should make everything appear as if
MSAA is disabled. However, it's undefined behavior if depth is
bound, so in that case, we can at least use a lowering pass to
make things *look* like MSAA is off, unless you use atomics to
count invocations.

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-13 16:44:32 -08:00 committed by Marge Bot
parent aef777c95d
commit e5cf19fced
5 changed files with 81 additions and 2 deletions

View file

@ -176,6 +176,9 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
NIR_PASS_V(nir, dxil_nir_lower_loads_stores_to_dxil);
NIR_PASS_V(nir, dxil_nir_lower_atomics_to_dxil);
if (key->fs.multisample_disabled)
NIR_PASS_V(nir, d3d12_disable_multisampling);
struct nir_to_dxil_options opts = {};
opts.interpolate_at_vertex = screen->have_load_at_vertex;
opts.lower_int16 = !screen->opts4.Native16BitShaderOpsSupported;
@ -619,7 +622,10 @@ d3d12_compare_shader_keys(const d3d12_shader_key *expect, const d3d12_shader_key
expect->fs.manual_depth_range != have->fs.manual_depth_range ||
expect->fs.polygon_stipple != have->fs.polygon_stipple ||
expect->fs.cast_to_uint != have->fs.cast_to_uint ||
expect->fs.cast_to_int != have->fs.cast_to_int)
expect->fs.cast_to_int != have->fs.cast_to_int ||
expect->fs.remap_front_facing != have->fs.remap_front_facing ||
expect->fs.missing_dual_src_outputs != have->fs.missing_dual_src_outputs ||
expect->fs.multisample_disabled != have->fs.multisample_disabled)
return false;
} else if (expect->stage == PIPE_SHADER_COMPUTE) {
if (memcmp(expect->cs.workgroup_size, have->cs.workgroup_size,
@ -760,6 +766,8 @@ d3d12_fill_shader_key(struct d3d12_selection_context *sel_ctx,
key->fs.frag_result_color_lowering = sel_ctx->frag_result_color_lowering;
key->fs.manual_depth_range = sel_ctx->manual_depth_range;
key->fs.polygon_stipple = sel_ctx->ctx->pstipple.enabled;
key->fs.multisample_disabled = sel_ctx->ctx->gfx_pipeline_state.rast &&
!sel_ctx->ctx->gfx_pipeline_state.rast->desc.MultisampleEnable;
if (sel_ctx->ctx->gfx_pipeline_state.blend &&
sel_ctx->ctx->gfx_pipeline_state.blend->desc.RenderTarget[0].LogicOpEnable &&
!sel_ctx->ctx->gfx_pipeline_state.has_float_rtv) {

View file

@ -118,6 +118,7 @@ struct d3d12_shader_key {
unsigned manual_depth_range : 1;
unsigned polygon_stipple : 1;
unsigned remap_front_facing : 1;
unsigned multisample_disabled : 1;
} fs;
struct {

View file

@ -878,3 +878,63 @@ d3d12_lower_sample_pos(nir_shader *s)
{
return nir_shader_lower_instructions(s, is_sample_pos, lower_sample_pos, NULL);
}
static bool
is_multisampling_instr(const nir_instr *instr, const void *_data)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic == nir_intrinsic_store_output) {
nir_io_semantics semantics = nir_intrinsic_io_semantics(intr);
return semantics.location == FRAG_RESULT_SAMPLE_MASK;
} else if (intr->intrinsic == nir_intrinsic_store_deref) {
nir_variable *var = nir_deref_instr_get_variable(nir_src_as_deref(intr->src[0]));
return var->data.location == FRAG_RESULT_SAMPLE_MASK;
} else if (intr->intrinsic == nir_intrinsic_load_sample_id ||
intr->intrinsic == nir_intrinsic_load_sample_mask_in)
return true;
return false;
}
static nir_ssa_def *
lower_multisampling_instr(nir_builder *b, nir_instr *instr, void *_data)
{
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
switch (intr->intrinsic) {
case nir_intrinsic_store_output:
case nir_intrinsic_store_deref:
return NIR_LOWER_INSTR_PROGRESS_REPLACE;
case nir_intrinsic_load_sample_id:
return nir_imm_int(b, 0);
case nir_intrinsic_load_sample_mask_in:
return nir_imm_int(b, 1);
default:
unreachable("Invalid intrinsic");
}
}
bool
d3d12_disable_multisampling(nir_shader *s)
{
if (s->info.stage != MESA_SHADER_FRAGMENT)
return false;
bool progress = nir_shader_lower_instructions(s, is_multisampling_instr, lower_multisampling_instr, NULL);
nir_foreach_variable_with_modes_safe(var, s, nir_var_shader_out) {
if (var->data.location == FRAG_RESULT_SAMPLE_MASK) {
exec_node_remove(&var->node);
progress = true;
}
}
nir_foreach_variable_with_modes_safe(var, s, nir_var_shader_in | nir_var_system_value) {
if (var->data.location == SYSTEM_VALUE_SAMPLE_MASK_IN ||
var->data.location == SYSTEM_VALUE_SAMPLE_ID) {
exec_node_remove(&var->node);
progress = true;
}
var->data.sample = false;
}
BITSET_CLEAR(s->info.system_values_read, SYSTEM_VALUE_SAMPLE_ID);
return progress;
}

View file

@ -101,6 +101,9 @@ d3d12_lower_image_casts(nir_shader *s, struct d3d12_image_format_conversion_info
bool
d3d12_lower_sample_pos(nir_shader *s);
bool
d3d12_disable_multisampling(nir_shader *s);
#ifdef __cplusplus
}
#endif

View file

@ -263,7 +263,14 @@ create_gfx_pipeline_state(struct d3d12_context *ctx)
if (state->num_cbufs || state->dsv_format != DXGI_FORMAT_UNKNOWN) {
pso_desc.SampleDesc.Count = state->samples;
} else {
if (!state->zsa->desc.DepthEnable &&
!state->zsa->desc.StencilEnable &&
!state->rast->desc.MultisampleEnable &&
state->samples > 1) {
pso_desc.RasterizerState.ForcedSampleCount = 1;
pso_desc.DSVFormat = DXGI_FORMAT_UNKNOWN;
}
} else if (state->samples > 1) {
pso_desc.SampleDesc.Count = 1;
pso_desc.RasterizerState.ForcedSampleCount = state->samples;
}