From aaa6fac8f65e6a28ba73eef6a0e6da4bef4fc992 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Mon, 25 Jun 2018 15:14:38 -0700 Subject: [PATCH] intel/blorp: Take an explicit filter parameter in blorp_blit This lets us move the glBlitFramebuffer nonsense into the GL driver and make the usage of BLORP mutch more explicit and obvious as to what it's doing. Reviewed-by: Chad Versace --- src/intel/blorp/blorp.h | 3 +- src/intel/blorp/blorp_blit.c | 44 ++----------------- src/intel/vulkan/anv_blorp.c | 34 +++++++++++---- src/mesa/drivers/dri/i965/brw_blorp.c | 63 ++++++++++++++++++++++++++- 4 files changed, 93 insertions(+), 51 deletions(-) diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h index 6e2f888d17f..ee343a4a6bb 100644 --- a/src/intel/blorp/blorp.h +++ b/src/intel/blorp/blorp.h @@ -139,7 +139,8 @@ blorp_blit(struct blorp_batch *batch, float src_x1, float src_y1, float dst_x0, float dst_y0, float dst_x1, float dst_y1, - uint32_t filter, bool mirror_x, bool mirror_y); + enum blorp_filter filter, + bool mirror_x, bool mirror_y); void blorp_copy(struct blorp_batch *batch, diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index cdabf441e52..a18f96a0ae1 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -2211,7 +2211,8 @@ blorp_blit(struct blorp_batch *batch, float src_x1, float src_y1, float dst_x0, float dst_y0, float dst_x1, float dst_y1, - GLenum filter, bool mirror_x, bool mirror_y) + enum blorp_filter filter, + bool mirror_x, bool mirror_y) { struct blorp_params params; blorp_params_init(¶ms); @@ -2240,14 +2241,10 @@ blorp_blit(struct blorp_batch *batch, params.dst.view.swizzle = dst_swizzle; struct brw_blorp_blit_prog_key wm_prog_key = { - .shader_type = BLORP_SHADER_TYPE_BLIT + .shader_type = BLORP_SHADER_TYPE_BLIT, + .filter = filter, }; - /* Scaled blitting or not. */ - const bool blit_scaled = - ((dst_x1 - dst_x0) == (src_x1 - src_x0) && - (dst_y1 - dst_y0) == (src_y1 - src_y0)) ? false : true; - /* Scaling factors used for bilinear filtering in multisample scaled * blits. */ @@ -2257,39 +2254,6 @@ blorp_blit(struct blorp_batch *batch, wm_prog_key.x_scale = 2.0f; wm_prog_key.y_scale = params.src.surf.samples / wm_prog_key.x_scale; - const bool bilinear_filter = filter == GL_LINEAR && - params.src.surf.samples <= 1 && - params.dst.surf.samples <= 1; - - /* If we are downsampling a non-integer color buffer, blend. - * - * Regarding integer color buffers, the OpenGL ES 3.2 spec says: - * - * "If the source formats are integer types or stencil values, a - * single sample's value is selected for each pixel." - * - * This implies we should not blend in that case. - */ - const bool blend = - (params.src.surf.usage & ISL_SURF_USAGE_DEPTH_BIT) == 0 && - (params.src.surf.usage & ISL_SURF_USAGE_STENCIL_BIT) == 0 && - !isl_format_has_int_channel(params.src.surf.format) && - params.src.surf.samples > 1 && - params.dst.surf.samples <= 1; - - if (blend && !blit_scaled) { - wm_prog_key.filter = BLORP_FILTER_AVERAGE; - } else if (blend && blit_scaled) { - wm_prog_key.filter = BLORP_FILTER_BILINEAR; - } else if (bilinear_filter) { - wm_prog_key.filter = BLORP_FILTER_BILINEAR; - } else { - if (params.src.surf.samples > 1) - wm_prog_key.filter = BLORP_FILTER_SAMPLE_0; - else - wm_prog_key.filter = BLORP_FILTER_NEAREST; - } - params.wm_inputs.rect_grid.x1 = minify(params.src.surf.logical_level0_px.width, src_level) * wm_prog_key.x_scale - 1.0f; diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index c76392fcd97..cd67cc636b2 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -513,13 +513,13 @@ void anv_CmdBlitImage( struct blorp_surf src, dst; - uint32_t gl_filter; + enum blorp_filter blorp_filter; switch (filter) { case VK_FILTER_NEAREST: - gl_filter = 0x2600; /* GL_NEAREST */ + blorp_filter = BLORP_FILTER_NEAREST; break; case VK_FILTER_LINEAR: - gl_filter = 0x2601; /* GL_LINEAR */ + blorp_filter = BLORP_FILTER_BILINEAR; break; default: unreachable("Invalid filter"); @@ -604,7 +604,7 @@ void anv_CmdBlitImage( dst_format.isl_format, dst_format.swizzle, src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, - gl_filter, flip_x, flip_y); + blorp_filter, flip_x, flip_y); } } @@ -1171,7 +1171,8 @@ resolve_surface(struct blorp_batch *batch, struct blorp_surf *dst_surf, uint32_t dst_level, uint32_t dst_layer, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - uint32_t width, uint32_t height) + uint32_t width, uint32_t height, + enum blorp_filter filter) { blorp_blit(batch, src_surf, src_level, src_layer, @@ -1180,7 +1181,7 @@ resolve_surface(struct blorp_batch *batch, ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY, src_x, src_y, src_x + width, src_y + height, dst_x, dst_y, dst_x + width, dst_y + height, - 0x2600 /* GL_NEAREST */, false, false); + filter, false, false); } static void @@ -1219,13 +1220,22 @@ resolve_image(struct anv_device *device, dst_surf.aux_usage, dst_level, dst_layer, 1); + enum blorp_filter filter; + if ((src_surf.surf->usage & ISL_SURF_USAGE_DEPTH_BIT) || + (src_surf.surf->usage & ISL_SURF_USAGE_STENCIL_BIT) || + isl_format_has_int_channel(src_surf.surf->format)) { + filter = BLORP_FILTER_SAMPLE_0; + } else { + filter = BLORP_FILTER_AVERAGE; + } + assert(!src_image->format->can_ycbcr); assert(!dst_image->format->can_ycbcr); resolve_surface(batch, &src_surf, src_level, src_layer, &dst_surf, dst_level, dst_layer, - src_x, src_y, dst_x, dst_y, width, height); + src_x, src_y, dst_x, dst_y, width, height, filter); } } @@ -1340,6 +1350,13 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer) assert(src_iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT && dst_iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT); + enum blorp_filter filter; + if (isl_format_has_int_channel(src_iview->planes[0].isl.format)) { + filter = BLORP_FILTER_SAMPLE_0; + } else { + filter = BLORP_FILTER_AVERAGE; + } + struct blorp_surf src_surf, dst_surf; get_blorp_surf_for_anv_image(cmd_buffer->device, src_iview->image, VK_IMAGE_ASPECT_COLOR_BIT, @@ -1381,7 +1398,8 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer) base_dst_layer + i, render_area.offset.x, render_area.offset.y, render_area.offset.x, render_area.offset.y, - render_area.extent.width, render_area.extent.height); + render_area.extent.width, render_area.extent.height, + filter); } } diff --git a/src/mesa/drivers/dri/i965/brw_blorp.c b/src/mesa/drivers/dri/i965/brw_blorp.c index 6192ace2253..b66ee18ba41 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp.c +++ b/src/mesa/drivers/dri/i965/brw_blorp.c @@ -283,7 +283,7 @@ brw_blorp_blit_miptrees(struct brw_context *brw, float src_x1, float src_y1, float dst_x0, float dst_y0, float dst_x1, float dst_y1, - GLenum filter, bool mirror_x, bool mirror_y, + GLenum gl_filter, bool mirror_x, bool mirror_y, bool decode_srgb, bool encode_srgb) { const struct gen_device_info *devinfo = &brw->screen->devinfo; @@ -320,6 +320,65 @@ brw_blorp_blit_miptrees(struct brw_context *brw, src_format = dst_format = MESA_FORMAT_R_FLOAT32; } + enum blorp_filter blorp_filter; + if (fabsf(dst_x1 - dst_x0) == fabsf(src_x1 - src_x0) && + fabsf(dst_y1 - dst_y0) == fabsf(src_y1 - src_y0)) { + if (src_mt->surf.samples > 1 && dst_mt->surf.samples <= 1) { + /* From the OpenGL ES 3.2 specification, section 16.2.1: + * + * "If the read framebuffer is multisampled (its effective value + * of SAMPLE_BUFFERS is one) and the draw framebuffer is not (its + * value of SAMPLE_BUFFERS is zero), the samples corresponding to + * each pixel location in the source are converted to a single + * sample before being written to the destination. The filter + * parameter is ignored. If the source formats are integer types + * or stencil values, a single sample’s value is selected for each + * pixel. If the source formats are floating-point or normalized + * types, the sample values for each pixel are resolved in an + * implementation-dependent manner. If the source formats are + * depth values, sample values are resolved in an implementation- + * dependent manner where the result will be between the minimum + * and maximum depth values in the pixel." + * + * For depth and stencil resolves, we choose to always use the value + * at sample 0. + */ + GLenum base_format = _mesa_get_format_base_format(src_mt->format); + if (base_format == GL_DEPTH_COMPONENT || + base_format == GL_STENCIL_INDEX || + base_format == GL_DEPTH_STENCIL || + _mesa_is_format_integer(src_mt->format)) { + /* The OpenGL ES 3.2 spec says: + * + * "If the source formats are integer types or stencil values, + * a single sample's value is selected for each pixel." + * + * Just take sample 0 in this case. + */ + blorp_filter = BLORP_FILTER_SAMPLE_0; + } else { + blorp_filter = BLORP_FILTER_AVERAGE; + } + } else { + /* From the OpenGL 4.6 specification, section 18.3.1: + * + * "If the source and destination dimensions are identical, no + * filtering is applied." + * + * Using BLORP_FILTER_NONE will also handle the upsample case by + * replicating the one value in the source to all values in the + * destination. + */ + blorp_filter = BLORP_FILTER_NONE; + } + } else if (gl_filter == GL_LINEAR || + gl_filter == GL_SCALED_RESOLVE_FASTEST_EXT || + gl_filter == GL_SCALED_RESOLVE_NICEST_EXT) { + blorp_filter = BLORP_FILTER_BILINEAR; + } else { + blorp_filter = BLORP_FILTER_NEAREST; + } + enum isl_format src_isl_format = brw_blorp_to_isl_format(brw, src_format, false); enum isl_aux_usage src_aux_usage = @@ -365,7 +424,7 @@ brw_blorp_blit_miptrees(struct brw_context *brw, dst_isl_format, ISL_SWIZZLE_IDENTITY, src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, - filter, mirror_x, mirror_y); + blorp_filter, mirror_x, mirror_y); blorp_batch_finish(&batch); intel_miptree_finish_write(brw, dst_mt, dst_level, dst_layer, 1, -- 2.30.2