intel/blorp: Add a partial resolve pass for MCS
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 23 Jun 2017 17:27:27 +0000 (10:27 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Sun, 23 Jul 2017 03:59:22 +0000 (20:59 -0700)
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/intel/blorp/blorp.h
src/intel/blorp/blorp_clear.c
src/intel/blorp/blorp_nir_builder.h [new file with mode: 0644]
src/intel/blorp/blorp_priv.h

index 1e96fb42b06a3334b52998185b0ee0a0b1a4261c..d19920e87f4939cf0459e702c2285fad0577130f 100644 (file)
@@ -205,6 +205,12 @@ blorp_ccs_resolve_attachment(struct blorp_batch *batch,
                              const enum isl_format format,
                              const enum blorp_fast_clear_op resolve_op);
 
+void
+blorp_mcs_partial_resolve(struct blorp_batch *batch,
+                          struct blorp_surf *surf,
+                          enum isl_format format,
+                          uint32_t start_layer, uint32_t num_layers);
+
 /**
  * For an overview of the HiZ operations, see the following sections of the
  * Sandy Bridge PRM, Volume 1, Part2:
index 581cf63c49f585ddfb3f791272011f762f32a87b..0feebefc575a4607f32061ca9f9a8debf8e70194 100644 (file)
@@ -29,7 +29,7 @@
 #include "blorp_priv.h"
 #include "compiler/brw_eu_defines.h"
 
-#include "compiler/nir/nir_builder.h"
+#include "blorp_nir_builder.h"
 
 #define FILE_DEBUG_FLAG DEBUG_BLORP
 
@@ -794,3 +794,106 @@ blorp_ccs_resolve_attachment(struct blorp_batch *batch,
 
    batch->blorp->exec(batch, &params);
 }
+
+struct blorp_mcs_partial_resolve_key
+{
+   enum blorp_shader_type shader_type;
+   uint32_t num_samples;
+};
+
+static bool
+blorp_params_get_mcs_partial_resolve_kernel(struct blorp_context *blorp,
+                                            struct blorp_params *params)
+{
+   const struct blorp_mcs_partial_resolve_key blorp_key = {
+      .shader_type = BLORP_SHADER_TYPE_MCS_PARTIAL_RESOLVE,
+      .num_samples = params->num_samples,
+   };
+
+   if (blorp->lookup_shader(blorp, &blorp_key, sizeof(blorp_key),
+                            &params->wm_prog_kernel, &params->wm_prog_data))
+      return true;
+
+   void *mem_ctx = ralloc_context(NULL);
+
+   nir_builder b;
+   nir_builder_init_simple_shader(&b, mem_ctx, MESA_SHADER_FRAGMENT, NULL);
+   b.shader->info.name = ralloc_strdup(b.shader, "BLORP-mcs-partial-resolve");
+
+   nir_variable *v_color =
+      BLORP_CREATE_NIR_INPUT(b.shader, clear_color, glsl_vec4_type());
+
+   nir_variable *frag_color =
+      nir_variable_create(b.shader, nir_var_shader_out,
+                          glsl_vec4_type(), "gl_FragColor");
+   frag_color->data.location = FRAG_RESULT_COLOR;
+
+   /* Do an MCS fetch and check if it is equal to the magic clear value */
+   nir_ssa_def *mcs =
+      blorp_nir_txf_ms_mcs(&b, nir_f2i32(&b, blorp_nir_frag_coord(&b)),
+                               nir_load_layer_id(&b));
+   nir_ssa_def *is_clear =
+      blorp_nir_mcs_is_clear_color(&b, mcs, blorp_key.num_samples);
+
+   /* If we aren't the clear value, discard. */
+   nir_intrinsic_instr *discard =
+      nir_intrinsic_instr_create(b.shader, nir_intrinsic_discard_if);
+   discard->src[0] = nir_src_for_ssa(nir_inot(&b, is_clear));
+   nir_builder_instr_insert(&b, &discard->instr);
+
+   nir_copy_var(&b, frag_color, v_color);
+
+   struct brw_wm_prog_key wm_key;
+   brw_blorp_init_wm_prog_key(&wm_key);
+   wm_key.tex.compressed_multisample_layout_mask = 1;
+   wm_key.tex.msaa_16 = blorp_key.num_samples == 16;
+   wm_key.multisample_fbo = true;
+
+   struct brw_wm_prog_data prog_data;
+   unsigned program_size;
+   const unsigned *program =
+      blorp_compile_fs(blorp, mem_ctx, b.shader, &wm_key, false,
+                       &prog_data, &program_size);
+
+   bool result =
+      blorp->upload_shader(blorp, &blorp_key, sizeof(blorp_key),
+                           program, program_size,
+                           &prog_data.base, sizeof(prog_data),
+                           &params->wm_prog_kernel, &params->wm_prog_data);
+
+   ralloc_free(mem_ctx);
+   return result;
+}
+
+void
+blorp_mcs_partial_resolve(struct blorp_batch *batch,
+                          struct blorp_surf *surf,
+                          enum isl_format format,
+                          uint32_t start_layer, uint32_t num_layers)
+{
+   struct blorp_params params;
+   blorp_params_init(&params);
+
+   assert(batch->blorp->isl_dev->info->gen >= 7);
+
+   params.x0 = 0;
+   params.y0 = 0;
+   params.x1 = surf->surf->logical_level0_px.width;
+   params.y1 = surf->surf->logical_level0_px.height;
+
+   brw_blorp_surface_info_init(batch->blorp, &params.src, surf, 0,
+                               start_layer, format, false);
+   brw_blorp_surface_info_init(batch->blorp, &params.dst, surf, 0,
+                               start_layer, format, true);
+
+   params.num_samples = params.dst.surf.samples;
+   params.num_layers = num_layers;
+
+   memcpy(&params.wm_inputs.clear_color,
+          surf->clear_color.f32, sizeof(float) * 4);
+
+   if (!blorp_params_get_mcs_partial_resolve_kernel(batch->blorp, &params))
+      return;
+
+   batch->blorp->exec(batch, &params);
+}
diff --git a/src/intel/blorp/blorp_nir_builder.h b/src/intel/blorp/blorp_nir_builder.h
new file mode 100644 (file)
index 0000000..7f23abd
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "compiler/nir/nir_builder.h"
+
+static inline nir_ssa_def *
+blorp_nir_frag_coord(nir_builder *b)
+{
+   nir_variable *frag_coord =
+      nir_variable_create(b->shader, nir_var_shader_in,
+                          glsl_vec4_type(), "gl_FragCoord");
+
+   frag_coord->data.location = VARYING_SLOT_POS;
+   frag_coord->data.origin_upper_left = true;
+
+   return nir_load_var(b, frag_coord);
+}
+
+static inline nir_ssa_def *
+blorp_nir_txf_ms_mcs(nir_builder *b, nir_ssa_def *xy_pos, nir_ssa_def *layer)
+{
+   nir_tex_instr *tex = nir_tex_instr_create(b->shader, 1);
+   tex->op = nir_texop_txf_ms_mcs;
+   tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
+   tex->dest_type = nir_type_int;
+
+   nir_ssa_def *coord;
+   if (layer) {
+      tex->is_array = true;
+      tex->coord_components = 3;
+      coord = nir_vec3(b, nir_channel(b, xy_pos, 0),
+                          nir_channel(b, xy_pos, 1),
+                          layer);
+   } else {
+      tex->is_array = false;
+      tex->coord_components = 2;
+      coord = nir_channels(b, xy_pos, 0x3);
+   }
+   tex->src[0].src_type = nir_tex_src_coord;
+   tex->src[0].src = nir_src_for_ssa(coord);
+
+   /* Blorp only has one texture and it's bound at unit 0 */
+   tex->texture_index = 0;
+   tex->sampler_index = 0;
+
+   nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
+   nir_builder_instr_insert(b, &tex->instr);
+
+   return &tex->dest.ssa;
+}
+
+static inline nir_ssa_def *
+blorp_nir_mcs_is_clear_color(nir_builder *b,
+                             nir_ssa_def *mcs,
+                             uint32_t samples)
+{
+   switch (samples) {
+   case 2:
+      /* Empirical evidence suggests that the value returned from the
+       * sampler is not always 0x3 for clear color so we need to mask it.
+       */
+      return nir_ieq(b, nir_iand(b, nir_channel(b, mcs, 0),
+                                    nir_imm_int(b, 0x3)),
+                    nir_imm_int(b, 0x3));
+
+   case 4:
+      return nir_ieq(b, nir_channel(b, mcs, 0), nir_imm_int(b, 0xff));
+
+   case 8:
+      return nir_ieq(b, nir_channel(b, mcs, 0), nir_imm_int(b, ~0));
+
+   case 16:
+      /* For 16x MSAA, the MCS is actually an ivec2 */
+      return nir_iand(b, nir_ieq(b, nir_channel(b, mcs, 0),
+                                    nir_imm_int(b, ~0)),
+                         nir_ieq(b, nir_channel(b, mcs, 1),
+                                    nir_imm_int(b, ~0)));
+
+   default:
+      unreachable("Invalid sample count");
+   }
+}
index b265362f9b1bc105420d17d3fd7fdb23db54b363..81bf8c66c661d8b900efaa8dcecd876a02bf9f24 100644 (file)
@@ -209,6 +209,7 @@ void blorp_params_init(struct blorp_params *params);
 enum blorp_shader_type {
    BLORP_SHADER_TYPE_BLIT,
    BLORP_SHADER_TYPE_CLEAR,
+   BLORP_SHADER_TYPE_MCS_PARTIAL_RESOLVE,
    BLORP_SHADER_TYPE_LAYER_OFFSET_VS,
    BLORP_SHADER_TYPE_GEN4_SF,
 };