From e5cf19fced6feff07bcd6b288f6370feb21a496f Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Thu, 13 Jan 2022 16:44:32 -0800 Subject: [PATCH] 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 Part-of: --- src/gallium/drivers/d3d12/d3d12_compiler.cpp | 10 +++- src/gallium/drivers/d3d12/d3d12_compiler.h | 1 + src/gallium/drivers/d3d12/d3d12_nir_passes.c | 60 ++++++++++++++++++++++ src/gallium/drivers/d3d12/d3d12_nir_passes.h | 3 ++ src/gallium/drivers/d3d12/d3d12_pipeline_state.cpp | 9 +++- 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp index 061bdd5..e2af760 100644 --- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp +++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp @@ -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) { diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.h b/src/gallium/drivers/d3d12/d3d12_compiler.h index fcab487..8729d7c 100644 --- a/src/gallium/drivers/d3d12/d3d12_compiler.h +++ b/src/gallium/drivers/d3d12/d3d12_compiler.h @@ -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 { diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.c b/src/gallium/drivers/d3d12/d3d12_nir_passes.c index 16065fc..38e0fc1 100644 --- a/src/gallium/drivers/d3d12/d3d12_nir_passes.c +++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.c @@ -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; +} diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.h b/src/gallium/drivers/d3d12/d3d12_nir_passes.h index 7b6d4a3..80aeb8d 100644 --- a/src/gallium/drivers/d3d12/d3d12_nir_passes.h +++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.h @@ -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 diff --git a/src/gallium/drivers/d3d12/d3d12_pipeline_state.cpp b/src/gallium/drivers/d3d12/d3d12_pipeline_state.cpp index cff2519..9d5b1bc 100644 --- a/src/gallium/drivers/d3d12/d3d12_pipeline_state.cpp +++ b/src/gallium/drivers/d3d12/d3d12_pipeline_state.cpp @@ -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; } -- 2.7.4