[Mesa-dev] [PATCH 14/15] i965/msaa: Implement manual blending operation for Gen7.
Kenneth Graunke
kenneth at whitecape.org
Tue May 22 08:04:04 PDT 2012
On 05/11/2012 11:03 AM, Paul Berry wrote:
> On Gen6, the blending necessary to blit an MSAA surface to a non-MSAA
> surface could be accomplished with a single texturing operation. On
> Gen7, the WM program must fetch each sample and blend them together
> manually. This patch implements the manual blend operation.
It would be nice to indicate why (although it wasn't hard to find):
From the Bspec/Shared Functions/Messages/Initiating Message/Message Types:
"[DevIVB+]: Number of Multisamples on the associated surface must be
MULTISAMPLECOUNT_1."
> ---
> src/mesa/drivers/dri/i965/brw_blorp_blit.cpp | 90 +++++++++++++++++++-------
> 1 files changed, 67 insertions(+), 23 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
> index 9b4aacb..ee65cd6 100644
> --- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
> @@ -372,11 +372,12 @@ private:
> void kill_if_outside_dst_rect();
> void translate_dst_to_src();
> void single_to_blend();
> - void sample();
> - void texel_fetch();
> + void manual_blend();
> + void sample(struct brw_reg dst);
> + void texel_fetch(struct brw_reg dst);
> void expand_to_32_bits(struct brw_reg src, struct brw_reg dst);
> - void texture_lookup(GLuint msg_type, const sampler_message_arg *args,
> - int num_args);
> + void texture_lookup(struct brw_reg dst, GLuint msg_type,
> + const sampler_message_arg *args, int num_args);
> void render_target_write();
>
> void *mem_ctx;
> @@ -400,8 +401,13 @@ private:
> struct brw_reg offset;
> } x_transform, y_transform;
>
> - /* Data returned from texture lookup (4 vec16's) */
> - struct brw_reg Rdata;
> + /* Data to be written to render target (4 vec16's) */
> + struct brw_reg result;
> +
> + /* Auxiliary storage for data returned by a sampling operation when
> + * blending (4 vec16's)
> + */
> + struct brw_reg texture_data;
>
> /* X coordinates. We have two of them so that we can perform coordinate
> * transformations easily.
> @@ -472,10 +478,8 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
> }
>
> if (key->blend) {
> - /* We are blending, which means we'll be using a SAMPLE message, which
> - * causes the hardware to pick up the all of the samples corresponding
> - * to this pixel and average them together. Since we'll be relying on
> - * the hardware to find all of the samples and combine them together,
> + /* We are blending, which means we won't have an opportunity to
> + * translate the tiling and sample count for the texture surface. So
> * the surface state for the texture must be configured with the correct
> * tiling and sample count.
> */
> @@ -557,8 +561,14 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
> * irrelevant, because we are going to fetch all samples.
> */
> if (key->blend) {
> - single_to_blend();
> - sample();
> + if (brw->intel.gen == 6) {
> + /* Gen6 hardware an automatically blend using the SAMPLE message */
> + single_to_blend();
> + sample(result);
> + } else {
> + /* Gen7+ hardware doesn't automaticaly blend. */
> + manual_blend();
> + }
> } else {
> /* We aren't blending, which means we just want to fetch a single sample
> * from the source surface. The address that we want to fetch from is
> @@ -586,7 +596,7 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
> * the texturing unit, will cause data to be read from the correct
> * memory location. So we can fetch the texel now.
> */
> - texel_fetch();
> + texel_fetch(result);
> }
>
> /* Finally, write the fetched (or blended) value to the render target and
> @@ -625,7 +635,8 @@ brw_blorp_blit_program::alloc_regs()
> prog_data.first_curbe_grf = reg;
> alloc_push_const_regs(reg);
> reg += BRW_BLORP_NUM_PUSH_CONST_REGS;
> - this->Rdata = vec16(brw_vec8_grf(reg, 0)); reg += 8;
> + this->result = vec16(brw_vec8_grf(reg, 0)); reg += 8;
> + this->texture_data = vec16(brw_vec8_grf(reg, 0)); reg += 8;
> for (int i = 0; i< 2; ++i) {
> this->x_coords[i]
> = vec16(retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW));
> @@ -966,19 +977,50 @@ brw_blorp_blit_program::single_to_blend()
> SWAP_XY_AND_XPYP();
> }
>
> +void
> +brw_blorp_blit_program::manual_blend()
> +{
> + /* TODO: support num_samples != 4 */
> + const int num_samples = 4;
> +
> + /* Gather sample 0 data first */
> + s_is_zero = true;
> + texel_fetch(result);
> +
> + /* Gather data for remaining samples and accumulate it into result. */
> + s_is_zero = false;
> + for (int i = 1; i< num_samples; ++i) {
> + brw_MOV(&func, S, brw_imm_uw(i));
> + texel_fetch(texture_data);
> +
> + /* TODO: should use a smaller loop bound for non-RGBA formats */
> + for (int j = 0; j< 4; ++j) {
> + brw_ADD(&func, offset(result, 2*j), offset(vec8(result), 2*j),
> + offset(vec8(texture_data), 2*j));
> + }
> + }
> +
> + /* Scale the result down by a factor of num_samples */
> + /* TODO: should use a smaller loop bound for non-RGBA formats */
> + for (int j = 0; j< 4; ++j) {
> + brw_MUL(&func, offset(result, 2*j), offset(vec8(result), 2*j),
> + brw_imm_f(1.0/num_samples));
> + }
> +}
> +
> /**
> * Emit code to look up a value in the texture using the SAMPLE message (which
> * does blending of MSAA surfaces).
> */
> void
> -brw_blorp_blit_program::sample()
> +brw_blorp_blit_program::sample(struct brw_reg dst)
> {
> static const sampler_message_arg args[2] = {
> SAMPLER_MESSAGE_ARG_U_FLOAT,
> SAMPLER_MESSAGE_ARG_V_FLOAT
> };
>
> - texture_lookup(GEN5_SAMPLER_MESSAGE_SAMPLE, args, ARRAY_SIZE(args));
> + texture_lookup(dst, GEN5_SAMPLER_MESSAGE_SAMPLE, args, ARRAY_SIZE(args));
> }
>
> /**
> @@ -986,7 +1028,7 @@ brw_blorp_blit_program::sample()
> * (which does a simple texel fetch).
> */
> void
> -brw_blorp_blit_program::texel_fetch()
> +brw_blorp_blit_program::texel_fetch(struct brw_reg dst)
> {
> static const sampler_message_arg gen6_args[5] = {
> SAMPLER_MESSAGE_ARG_U_INT,
> @@ -1008,16 +1050,16 @@ brw_blorp_blit_program::texel_fetch()
>
> switch (brw->intel.gen) {
> case 6:
> - texture_lookup(GEN5_SAMPLER_MESSAGE_SAMPLE_LD, gen6_args,
> + texture_lookup(dst, GEN5_SAMPLER_MESSAGE_SAMPLE_LD, gen6_args,
> s_is_zero ? 2 : 5);
> break;
> case 7:
> if (key->tex_samples> 0) {
> - texture_lookup(GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DSS,
> + texture_lookup(dst, GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DSS,
> gen7_ld2dss_args, ARRAY_SIZE(gen7_ld2dss_args));
> } else {
> assert(s_is_zero);
> - texture_lookup(GEN5_SAMPLER_MESSAGE_SAMPLE_LD, gen7_ld_args,
> + texture_lookup(dst, GEN5_SAMPLER_MESSAGE_SAMPLE_LD, gen7_ld_args,
> ARRAY_SIZE(gen7_ld_args));
> }
> break;
> @@ -1038,7 +1080,8 @@ brw_blorp_blit_program::expand_to_32_bits(struct brw_reg src,
> }
>
> void
> -brw_blorp_blit_program::texture_lookup(GLuint msg_type,
> +brw_blorp_blit_program::texture_lookup(struct brw_reg dst,
> + GLuint msg_type,
> const sampler_message_arg *args,
> int num_args)
> {
> @@ -1072,7 +1115,7 @@ brw_blorp_blit_program::texture_lookup(GLuint msg_type,
> }
>
> brw_SAMPLE(&func,
> - retype(Rdata, BRW_REGISTER_TYPE_UW) /* dest */,
> + retype(dst, BRW_REGISTER_TYPE_UW) /* dest */,
> base_mrf /* msg_reg_nr */,
> brw_message_reg(base_mrf) /* src0 */,
> BRW_BLORP_TEXTURE_BINDING_TABLE_INDEX,
> @@ -1113,7 +1156,8 @@ brw_blorp_blit_program::render_target_write()
> /* Copy texture data to MRFs */
> for (int i = 0; i< 4; ++i) {
> /* E.g. mov(16) m2.0<1>:f r2.0<8;8,1>:f { Align1, H1 } */
> - brw_MOV(&func, offset(mrf_rt_write, mrf_offset), offset(vec8(Rdata), 2*i));
> + brw_MOV(&func, offset(mrf_rt_write, mrf_offset),
> + offset(vec8(result), 2*i));
> mrf_offset += 2;
> }
More information about the mesa-dev
mailing list