From c9cb37b2a6c3a63eb1caeb8eafe1c14b538056b4 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 23 Jun 2017 10:27:27 -0700 Subject: [PATCH] intel/blorp: Add a partial resolve pass for MCS Reviewed-by: Topi Pohjolainen --- src/intel/blorp/blorp.h | 6 ++ src/intel/blorp/blorp_clear.c | 105 +++++++++++++++++++++++++++- src/intel/blorp/blorp_nir_builder.h | 102 +++++++++++++++++++++++++++ src/intel/blorp/blorp_priv.h | 1 + 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 src/intel/blorp/blorp_nir_builder.h diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h index 1e96fb42b06..d19920e87f4 100644 --- a/src/intel/blorp/blorp.h +++ b/src/intel/blorp/blorp.h @@ -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: diff --git a/src/intel/blorp/blorp_clear.c b/src/intel/blorp/blorp_clear.c index 581cf63c49f..0feebefc575 100644 --- a/src/intel/blorp/blorp_clear.c +++ b/src/intel/blorp/blorp_clear.c @@ -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, ¶ms); } + +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), + ¶ms->wm_prog_kernel, ¶ms->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), + ¶ms->wm_prog_kernel, ¶ms->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(¶ms); + + 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, ¶ms.src, surf, 0, + start_layer, format, false); + brw_blorp_surface_info_init(batch->blorp, ¶ms.dst, surf, 0, + start_layer, format, true); + + params.num_samples = params.dst.surf.samples; + params.num_layers = num_layers; + + memcpy(¶ms.wm_inputs.clear_color, + surf->clear_color.f32, sizeof(float) * 4); + + if (!blorp_params_get_mcs_partial_resolve_kernel(batch->blorp, ¶ms)) + return; + + batch->blorp->exec(batch, ¶ms); +} diff --git a/src/intel/blorp/blorp_nir_builder.h b/src/intel/blorp/blorp_nir_builder.h new file mode 100644 index 00000000000..7f23abdef4d --- /dev/null +++ b/src/intel/blorp/blorp_nir_builder.h @@ -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"); + } +} diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h index b265362f9b1..81bf8c66c66 100644 --- a/src/intel/blorp/blorp_priv.h +++ b/src/intel/blorp/blorp_priv.h @@ -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, }; -- 2.30.2