d3d12: Modify shaders when MSAA is disabled
authorJesse Natalie <jenatali@microsoft.com>
Fri, 14 Jan 2022 00:44:32 +0000 (16:44 -0800)
committerMarge Bot <emma+marge@anholt.net>
Fri, 21 Jan 2022 23:08:26 +0000 (23:08 +0000)
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>

src/gallium/drivers/d3d12/d3d12_compiler.cpp
src/gallium/drivers/d3d12/d3d12_compiler.h
src/gallium/drivers/d3d12/d3d12_nir_passes.c
src/gallium/drivers/d3d12/d3d12_nir_passes.h
src/gallium/drivers/d3d12/d3d12_pipeline_state.cpp

index 061bdd5..e2af760 100644 (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) {
index fcab487..8729d7c 100644 (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 {
index 16065fc..38e0fc1 100644 (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;
+}
index 7b6d4a3..80aeb8d 100644 (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
index cff2519..9d5b1bc 100644 (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;
    }