diff options
-rw-r--r-- | src/mesa/drivers/dri/i965/Makefile.sources | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_blorp_blit.cpp | 1288 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_blorp_blit_eu.cpp | 145 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_blorp_blit_eu.h | 212 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_defines.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 21 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_shader.cpp | 2 |
8 files changed, 8 insertions, 1664 deletions
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources index fa5cf5a477c..e94605e4714 100644 --- a/src/mesa/drivers/dri/i965/Makefile.sources +++ b/src/mesa/drivers/dri/i965/Makefile.sources @@ -99,8 +99,6 @@ i965_compiler_GENERATED_FILES = \ i965_FILES = \ brw_binding_tables.c \ brw_blorp_blit.cpp \ - brw_blorp_blit_eu.cpp \ - brw_blorp_blit_eu.h \ brw_blorp_clear.cpp \ brw_blorp.c \ brw_blorp.h \ diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp index 26b5cbff663..77e5c2ba189 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp +++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp @@ -31,7 +31,6 @@ #include "brw_blorp.h" #include "brw_context.h" -#include "brw_blorp_blit_eu.h" #include "brw_state.h" #include "brw_meta_util.h" @@ -1436,1236 +1435,6 @@ brw_blorp_build_nir_shader(struct brw_context *brw, return b.shader; } -class brw_blorp_blit_program : public brw_blorp_eu_emitter -{ -public: - brw_blorp_blit_program(struct brw_context *brw, - const brw_blorp_blit_prog_key *key); - - const GLuint *compile(struct brw_context *brw, bool debug_flag, - GLuint *program_size); - - brw_blorp_prog_data prog_data; - -private: - void alloc_regs(); - void alloc_push_const_regs(int base_reg); - void compute_frag_coords(); - void translate_tiling(bool old_tiled_w, bool new_tiled_w); - void encode_msaa(unsigned num_samples, intel_msaa_layout layout); - void decode_msaa(unsigned num_samples, intel_msaa_layout layout); - void translate_dst_to_src(); - void clamp_tex_coords(struct brw_reg regX, struct brw_reg regY, - struct brw_reg clampX0, struct brw_reg clampY0, - struct brw_reg clampX1, struct brw_reg clampY1); - void single_to_blend(); - void manual_blend_average(unsigned num_samples); - void manual_blend_bilinear(unsigned num_samples); - void sample(struct brw_reg dst); - void texel_fetch(struct brw_reg dst); - void mcs_fetch(); - void texture_lookup(struct brw_reg dst, enum opcode op, - const sampler_message_arg *args, int num_args); - void render_target_write(); - - /** - * Base-2 logarithm of the maximum number of samples that can be blended. - */ - static const unsigned LOG2_MAX_BLEND_SAMPLES = 3; - - struct brw_context *brw; - const brw_blorp_blit_prog_key *key; - - /* Thread dispatch header */ - struct brw_reg R0; - - /* Pixel X/Y coordinates (always in R1). */ - struct brw_reg R1; - - /* Push constants */ - struct brw_reg dst_x0; - struct brw_reg dst_x1; - struct brw_reg dst_y0; - struct brw_reg dst_y1; - /* Top right coordinates of the rectangular grid used for scaled blitting */ - struct brw_reg rect_grid_x1; - struct brw_reg rect_grid_y1; - struct { - struct brw_reg multiplier; - struct brw_reg offset; - } x_transform, y_transform; - struct brw_reg src_z; - - /* Data read from texture (4 vec16's per array element) */ - struct brw_reg texture_data[LOG2_MAX_BLEND_SAMPLES + 1]; - - /* Auxiliary storage for the contents of the MCS surface. - * - * Since the sampler always returns 8 registers worth of data, this is 8 - * registers wide, even though we only use the first 2 registers of it. - */ - struct brw_reg mcs_data; - - /* X coordinates. We have two of them so that we can perform coordinate - * transformations easily. - */ - struct brw_reg x_coords[2]; - - /* Y coordinates. We have two of them so that we can perform coordinate - * transformations easily. - */ - struct brw_reg y_coords[2]; - - /* X, Y coordinates of the pixel from which we need to fetch the specific - * sample. These are used for multisample scaled blitting. - */ - struct brw_reg x_sample_coords; - struct brw_reg y_sample_coords; - - /* Fractional parts of the x and y coordinates, used as bilinear interpolation coefficients */ - struct brw_reg x_frac; - struct brw_reg y_frac; - - /* Which element of x_coords and y_coords is currently in use. - */ - int xy_coord_index; - - /* True if, at the point in the program currently being compiled, the - * sample index is known to be zero. - */ - bool s_is_zero; - - /* Register storing the sample index when s_is_zero is false. */ - struct brw_reg sample_index; - - /* Temporaries */ - struct brw_reg t1; - struct brw_reg t2; - - /* MRF used for sampling and render target writes */ - GLuint base_mrf; -}; - -brw_blorp_blit_program::brw_blorp_blit_program( - struct brw_context *brw, const brw_blorp_blit_prog_key *key) - : brw_blorp_eu_emitter(), brw(brw), key(key) -{ -} - -const GLuint * -brw_blorp_blit_program::compile(struct brw_context *brw, bool debug_flag, - GLuint *program_size) -{ - /* Sanity checks */ - if (key->dst_tiled_w && key->rt_samples > 0) { - /* If the destination image is W tiled and multisampled, then the thread - * must be dispatched once per sample, not once per pixel. This is - * necessary because after conversion between W and Y tiling, there's no - * guarantee that all samples corresponding to a single pixel will still - * be together. - */ - assert(key->persample_msaa_dispatch); - } - - if (key->blend) { - /* 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. - */ - assert(!key->src_tiled_w); - assert(key->tex_samples == key->src_samples); - assert(key->tex_layout == key->src_layout); - assert(key->tex_samples > 0); - } - - if (key->persample_msaa_dispatch) { - /* It only makes sense to do persample dispatch if the render target is - * configured as multisampled. - */ - assert(key->rt_samples > 0); - } - - /* Make sure layout is consistent with sample count */ - assert((key->tex_layout == INTEL_MSAA_LAYOUT_NONE) == - (key->tex_samples == 0)); - assert((key->rt_layout == INTEL_MSAA_LAYOUT_NONE) == - (key->rt_samples == 0)); - assert((key->src_layout == INTEL_MSAA_LAYOUT_NONE) == - (key->src_samples == 0)); - assert((key->dst_layout == INTEL_MSAA_LAYOUT_NONE) == - (key->dst_samples == 0)); - - /* Set up prog_data */ - brw_blorp_prog_data_init(&prog_data); - prog_data.persample_msaa_dispatch = key->persample_msaa_dispatch; - - alloc_regs(); - compute_frag_coords(); - - /* Render target and texture hardware don't support W tiling until Gen8. */ - const bool rt_tiled_w = false; - const bool tex_tiled_w = brw->gen >= 8 && key->src_tiled_w; - - /* The address that data will be written to is determined by the - * coordinates supplied to the WM thread and the tiling and sample count of - * the render target, according to the formula: - * - * (X, Y, S) = decode_msaa(rt_samples, detile(rt_tiling, offset)) - * - * If the actual tiling and sample count of the destination surface are not - * the same as the configuration of the render target, then these - * coordinates are wrong and we have to adjust them to compensate for the - * difference. - */ - if (rt_tiled_w != key->dst_tiled_w || - key->rt_samples != key->dst_samples || - key->rt_layout != key->dst_layout) { - encode_msaa(key->rt_samples, key->rt_layout); - /* Now (X, Y, S) = detile(rt_tiling, offset) */ - translate_tiling(rt_tiled_w, key->dst_tiled_w); - /* Now (X, Y, S) = detile(dst_tiling, offset) */ - decode_msaa(key->dst_samples, key->dst_layout); - } - - /* Now (X, Y, S) = decode_msaa(dst_samples, detile(dst_tiling, offset)). - * - * That is: X, Y and S now contain the true coordinates and sample index of - * the data that the WM thread should output. - * - * If we need to kill pixels that are outside the destination rectangle, - * now is the time to do it. - */ - - if (key->use_kill) - emit_kill_if_outside_rect(x_coords[xy_coord_index], - y_coords[xy_coord_index], - dst_x0, dst_x1, dst_y0, dst_y1); - - /* Next, apply a translation to obtain coordinates in the source image. */ - translate_dst_to_src(); - - /* If the source image is not multisampled, then we want to fetch sample - * number 0, because that's the only sample there is. - */ - if (key->src_samples == 0) - s_is_zero = true; - - /* X, Y, and S are now the coordinates of the pixel in the source image - * that we want to texture from. Exception: if we are blending, then S is - * irrelevant, because we are going to fetch all samples. - */ - if (key->blend && !key->blit_scaled) { - if (brw->gen == 6) { - /* Gen6 hardware an automatically blend using the SAMPLE message */ - single_to_blend(); - sample(texture_data[0]); - } else { - /* Gen7+ hardware doesn't automaticaly blend. */ - manual_blend_average(key->src_samples); - } - } else if(key->blend && key->blit_scaled) { - manual_blend_bilinear(key->src_samples); - } 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 - * related to the X, Y and S values according to the formula: - * - * (X, Y, S) = decode_msaa(src_samples, detile(src_tiling, offset)). - * - * If the actual tiling and sample count of the source surface are not - * the same as the configuration of the texture, then we need to adjust - * the coordinates to compensate for the difference. - */ - if ((tex_tiled_w != key->src_tiled_w || - key->tex_samples != key->src_samples || - key->tex_layout != key->src_layout) && - !key->bilinear_filter) { - encode_msaa(key->src_samples, key->src_layout); - /* Now (X, Y, S) = detile(src_tiling, offset) */ - translate_tiling(key->src_tiled_w, tex_tiled_w); - /* Now (X, Y, S) = detile(tex_tiling, offset) */ - decode_msaa(key->tex_samples, key->tex_layout); - } - - if (key->bilinear_filter) { - sample(texture_data[0]); - } - else { - /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)). - * - * In other words: X, Y, and S now contain values which, when passed to - * the texturing unit, will cause data to be read from the correct - * memory location. So we can fetch the texel now. - */ - if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) - mcs_fetch(); - texel_fetch(texture_data[0]); - } - } - - /* Finally, write the fetched (or blended) value to the render target and - * terminate the thread. - */ - render_target_write(); - - return get_program(brw, debug_flag, program_size); -} - -void -brw_blorp_blit_program::alloc_push_const_regs(int base_reg) -{ -#define CONST_LOC(name) offsetof(brw_blorp_wm_push_constants, name) -#define ALLOC_REG(name, type) \ - this->name = \ - retype(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, \ - base_reg + CONST_LOC(name) / 32, \ - (CONST_LOC(name) % 32) / 4), type) - - ALLOC_REG(dst_x0, BRW_REGISTER_TYPE_UD); - ALLOC_REG(dst_x1, BRW_REGISTER_TYPE_UD); - ALLOC_REG(dst_y0, BRW_REGISTER_TYPE_UD); - ALLOC_REG(dst_y1, BRW_REGISTER_TYPE_UD); - ALLOC_REG(rect_grid_x1, BRW_REGISTER_TYPE_F); - ALLOC_REG(rect_grid_y1, BRW_REGISTER_TYPE_F); - ALLOC_REG(x_transform.multiplier, BRW_REGISTER_TYPE_F); - ALLOC_REG(x_transform.offset, BRW_REGISTER_TYPE_F); - ALLOC_REG(y_transform.multiplier, BRW_REGISTER_TYPE_F); - ALLOC_REG(y_transform.offset, BRW_REGISTER_TYPE_F); - ALLOC_REG(src_z, BRW_REGISTER_TYPE_UD); -#undef CONST_LOC -#undef ALLOC_REG -} - -void -brw_blorp_blit_program::alloc_regs() -{ - int reg = 0; - this->R0 = retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW); - this->R1 = retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW); - prog_data.first_curbe_grf_0 = reg; - alloc_push_const_regs(reg); - reg += BRW_BLORP_NUM_PUSH_CONST_REGS; - for (unsigned i = 0; i < ARRAY_SIZE(texture_data); ++i) { - this->texture_data[i] = - retype(vec16(brw_vec8_grf(reg, 0)), key->texture_data_type); - reg += 8; - } - this->mcs_data = - retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); reg += 8; - - for (int i = 0; i < 2; ++i) { - this->x_coords[i] - = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); - reg += 2; - this->y_coords[i] - = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); - reg += 2; - } - - if (key->blit_scaled && key->blend) { - this->x_sample_coords = brw_vec8_grf(reg, 0); - reg += 2; - this->y_sample_coords = brw_vec8_grf(reg, 0); - reg += 2; - this->x_frac = brw_vec8_grf(reg, 0); - reg += 2; - this->y_frac = brw_vec8_grf(reg, 0); - reg += 2; - } - - this->xy_coord_index = 0; - this->sample_index - = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); - reg += 2; - this->t1 = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); - reg += 2; - this->t2 = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); - reg += 2; - - /* Make sure we didn't run out of registers */ - assert(reg <= GEN7_MRF_HACK_START); - - int mrf = 2; - this->base_mrf = mrf; -} - -/* In the code that follows, X and Y can be used to quickly refer to the - * active elements of x_coords and y_coords, and Xp and Yp ("X prime" and "Y - * prime") to the inactive elements. - * - * S can be used to quickly refer to sample_index. - */ -#define X x_coords[xy_coord_index] -#define Y y_coords[xy_coord_index] -#define Xp x_coords[!xy_coord_index] -#define Yp y_coords[!xy_coord_index] -#define S sample_index - -/* Quickly swap the roles of (X, Y) and (Xp, Yp). Saves us from having to do - * MOVs to transfor (Xp, Yp) to (X, Y) after a coordinate transformation. - */ -#define SWAP_XY_AND_XPYP() xy_coord_index = !xy_coord_index; - -/** - * Emit code to compute the X and Y coordinates of the pixels being rendered - * by this WM invocation. - * - * Assuming the render target is set up for Y tiling, these (X, Y) values are - * related to the address offset where outputs will be written by the formula: - * - * (X, Y, S) = decode_msaa(detile(offset)). - * - * (See brw_blorp_blit_program). - */ -void -brw_blorp_blit_program::compute_frag_coords() -{ - /* R1.2[15:0] = X coordinate of upper left pixel of subspan 0 (pixel 0) - * R1.3[15:0] = X coordinate of upper left pixel of subspan 1 (pixel 4) - * R1.4[15:0] = X coordinate of upper left pixel of subspan 2 (pixel 8) - * R1.5[15:0] = X coordinate of upper left pixel of subspan 3 (pixel 12) - * - * Pixels within a subspan are laid out in this arrangement: - * 0 1 - * 2 3 - * - * So, to compute the coordinates of each pixel, we need to read every 2nd - * 16-bit value (vstride=2) from R1, starting at the 4th 16-bit value - * (suboffset=4), and duplicate each value 4 times (hstride=0, width=4). - * In other words, the data we want to access is R1.4<2;4,0>UW. - * - * Then, we need to add the repeating sequence (0, 1, 0, 1, ...) to the - * result, since pixels n+1 and n+3 are in the right half of the subspan. - */ - emit_add(vec16(retype(X, BRW_REGISTER_TYPE_UW)), - stride(suboffset(R1, 4), 2, 4, 0), brw_imm_v(0x10101010)); - - /* Similarly, Y coordinates for subspans come from R1.2[31:16] through - * R1.5[31:16], so to get pixel Y coordinates we need to start at the 5th - * 16-bit value instead of the 4th (R1.5<2;4,0>UW instead of - * R1.4<2;4,0>UW). - * - * And we need to add the repeating sequence (0, 0, 1, 1, ...), since - * pixels n+2 and n+3 are in the bottom half of the subspan. - */ - emit_add(vec16(retype(Y, BRW_REGISTER_TYPE_UW)), - stride(suboffset(R1, 5), 2, 4, 0), brw_imm_v(0x11001100)); - - /* Move the coordinates to UD registers. */ - emit_mov(vec16(Xp), retype(X, BRW_REGISTER_TYPE_UW)); - emit_mov(vec16(Yp), retype(Y, BRW_REGISTER_TYPE_UW)); - SWAP_XY_AND_XPYP(); - - if (key->persample_msaa_dispatch) { - switch (key->rt_samples) { - case 2: - case 4: { - /* The WM will be run in MSDISPMODE_PERSAMPLE with num_samples == 4. - * Therefore, subspan 0 will represent sample 0, subspan 1 will - * represent sample 1, and so on. - * - * So we need to populate S with the sequence (0, 0, 0, 0, 1, 1, 1, - * 1, 2, 2, 2, 2, 3, 3, 3, 3). The easiest way to do this is to - * populate a temporary variable with the sequence (0, 1, 2, 3), and - * then copy from it using vstride=1, width=4, hstride=0. - */ - struct brw_reg t1_uw1 = retype(t1, BRW_REGISTER_TYPE_UW); - emit_mov(vec16(t1_uw1), key->rt_samples == 4 ? - brw_imm_v(0x3210) : brw_imm_v(0x1010)); - /* Move to UD sample_index register. */ - emit_mov_8(S, stride(t1_uw1, 1, 4, 0)); - emit_mov_8(offset(S, 1), suboffset(stride(t1_uw1, 1, 4, 0), 2)); - break; - } - case 8: { - /* The WM will be run in MSDISPMODE_PERSAMPLE with num_samples == 8. - * Therefore, subspan 0 will represent sample N (where N is 0 or 4), - * subspan 1 will represent sample 1, and so on. We can find the - * value of N by looking at R0.0 bits 7:6 ("Starting Sample Pair - * Index") and multiplying by two (since samples are always delivered - * in pairs). That is, we compute 2*((R0.0 & 0xc0) >> 6) == (R0.0 & - * 0xc0) >> 5. - * - * Then we need to add N to the sequence (0, 0, 0, 0, 1, 1, 1, 1, 2, - * 2, 2, 2, 3, 3, 3, 3), which we compute by populating a temporary - * variable with the sequence (0, 1, 2, 3), and then reading from it - * using vstride=1, width=4, hstride=0. - */ - struct brw_reg t1_ud1 = vec1(retype(t1, BRW_REGISTER_TYPE_UD)); - struct brw_reg t2_uw1 = retype(t2, BRW_REGISTER_TYPE_UW); - struct brw_reg r0_ud1 = vec1(retype(R0, BRW_REGISTER_TYPE_UD)); - emit_and(t1_ud1, r0_ud1, brw_imm_ud(0xc0)); - emit_shr(t1_ud1, t1_ud1, brw_imm_ud(5)); - emit_mov(vec16(t2_uw1), brw_imm_v(0x3210)); - emit_add(vec16(S), retype(t1_ud1, BRW_REGISTER_TYPE_UW), - stride(t2_uw1, 1, 4, 0)); - emit_add_8(offset(S, 1), - retype(t1_ud1, BRW_REGISTER_TYPE_UW), - suboffset(stride(t2_uw1, 1, 4, 0), 2)); - break; - } - default: - unreachable("Unrecognized sample count in " - "brw_blorp_blit_program::compute_frag_coords()"); - } - s_is_zero = false; - } else { - /* Either the destination surface is single-sampled, or the WM will be - * run in MSDISPMODE_PERPIXEL (which causes a single fragment dispatch - * per pixel). In either case, it's not meaningful to compute a sample - * value. Just set it to 0. - */ - s_is_zero = true; - } -} - -/** - * Emit code to compensate for the difference between Y and W tiling. - * - * This code modifies the X and Y coordinates according to the formula: - * - * (X', Y', S') = detile(new_tiling, tile(old_tiling, X, Y, S)) - * - * (See brw_blorp_blit_program). - * - * It can only translate between W and Y tiling, so new_tiling and old_tiling - * are booleans where true represents W tiling and false represents Y tiling. - */ -void -brw_blorp_blit_program::translate_tiling(bool old_tiled_w, bool new_tiled_w) -{ - if (old_tiled_w == new_tiled_w) - return; - - /* In the code that follows, we can safely assume that S = 0, because W - * tiling formats always use IMS layout. - */ - assert(s_is_zero); - - if (new_tiled_w) { - /* Given X and Y coordinates that describe an address using Y tiling, - * translate to the X and Y coordinates that describe the same address - * using W tiling. - * - * If we break down the low order bits of X and Y, using a - * single letter to represent each low-order bit: - * - * X = A << 7 | 0bBCDEFGH - * Y = J << 5 | 0bKLMNP (1) - * - * Then we can apply the Y tiling formula to see the memory offset being - * addressed: - * - * offset = (J * tile_pitch + A) << 12 | 0bBCDKLMNPEFGH (2) - * - * If we apply the W detiling formula to this memory location, that the - * corresponding X' and Y' coordinates are: - * - * X' = A << 6 | 0bBCDPFH (3) - * Y' = J << 6 | 0bKLMNEG - * - * Combining (1) and (3), we see that to transform (X, Y) to (X', Y'), - * we need to make the following computation: - * - * X' = (X & ~0b1011) >> 1 | (Y & 0b1) << 2 | X & 0b1 (4) - * Y' = (Y & ~0b1) << 1 | (X & 0b1000) >> 2 | (X & 0b10) >> 1 - */ - emit_and(t1, X, brw_imm_uw(0xfff4)); /* X & ~0b1011 */ - emit_shr(t1, t1, brw_imm_uw(1)); /* (X & ~0b1011) >> 1 */ - emit_and(t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ - emit_shl(t2, t2, brw_imm_uw(2)); /* (Y & 0b1) << 2 */ - emit_or(t1, t1, t2); /* (X & ~0b1011) >> 1 | (Y & 0b1) << 2 */ - emit_and(t2, X, brw_imm_uw(1)); /* X & 0b1 */ - emit_or(Xp, t1, t2); - emit_and(t1, Y, brw_imm_uw(0xfffe)); /* Y & ~0b1 */ - emit_shl(t1, t1, brw_imm_uw(1)); /* (Y & ~0b1) << 1 */ - emit_and(t2, X, brw_imm_uw(8)); /* X & 0b1000 */ - emit_shr(t2, t2, brw_imm_uw(2)); /* (X & 0b1000) >> 2 */ - emit_or(t1, t1, t2); /* (Y & ~0b1) << 1 | (X & 0b1000) >> 2 */ - emit_and(t2, X, brw_imm_uw(2)); /* X & 0b10 */ - emit_shr(t2, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ - emit_or(Yp, t1, t2); - SWAP_XY_AND_XPYP(); - } else { - /* Applying the same logic as above, but in reverse, we obtain the - * formulas: - * - * X' = (X & ~0b101) << 1 | (Y & 0b10) << 2 | (Y & 0b1) << 1 | X & 0b1 - * Y' = (Y & ~0b11) >> 1 | (X & 0b100) >> 2 - */ - emit_and(t1, X, brw_imm_uw(0xfffa)); /* X & ~0b101 */ - emit_shl(t1, t1, brw_imm_uw(1)); /* (X & ~0b101) << 1 */ - emit_and(t2, Y, brw_imm_uw(2)); /* Y & 0b10 */ - emit_shl(t2, t2, brw_imm_uw(2)); /* (Y & 0b10) << 2 */ - emit_or(t1, t1, t2); /* (X & ~0b101) << 1 | (Y & 0b10) << 2 */ - emit_and(t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ - emit_shl(t2, t2, brw_imm_uw(1)); /* (Y & 0b1) << 1 */ - emit_or(t1, t1, t2); /* (X & ~0b101) << 1 | (Y & 0b10) << 2 - | (Y & 0b1) << 1 */ - emit_and(t2, X, brw_imm_uw(1)); /* X & 0b1 */ - emit_or(Xp, t1, t2); - emit_and(t1, Y, brw_imm_uw(0xfffc)); /* Y & ~0b11 */ - emit_shr(t1, t1, brw_imm_uw(1)); /* (Y & ~0b11) >> 1 */ - emit_and(t2, X, brw_imm_uw(4)); /* X & 0b100 */ - emit_shr(t2, t2, brw_imm_uw(2)); /* (X & 0b100) >> 2 */ - emit_or(Yp, t1, t2); - SWAP_XY_AND_XPYP(); - } -} - -/** - * Emit code to compensate for the difference between MSAA and non-MSAA - * surfaces. - * - * This code modifies the X and Y coordinates according to the formula: - * - * (X', Y', S') = encode_msaa(num_samples, IMS, X, Y, S) - * - * (See brw_blorp_blit_program). - */ -void -brw_blorp_blit_program::encode_msaa(unsigned num_samples, - intel_msaa_layout layout) -{ - switch (layout) { - case INTEL_MSAA_LAYOUT_NONE: - /* No translation necessary, and S should already be zero. */ - assert(s_is_zero); - break; - case INTEL_MSAA_LAYOUT_CMS: - /* We can't compensate for compressed layout since at this point in the - * program we haven't read from the MCS buffer. - */ - unreachable("Bad layout in encode_msaa"); - case INTEL_MSAA_LAYOUT_UMS: - /* No translation necessary. */ - break; - case INTEL_MSAA_LAYOUT_IMS: - switch (num_samples) { - case 2: - /* encode_msaa(2, IMS, X, Y, S) = (X', Y', 0) - * where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1) - * Y' = Y - */ - case 4: - /* encode_msaa(4, IMS, X, Y, S) = (X', Y', 0) - * where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1) - * Y' = (Y & ~0b1) << 1 | (S & 0b10) | (Y & 0b1) - */ - emit_and(t1, X, brw_imm_uw(0xfffe)); /* X & ~0b1 */ - if (!s_is_zero) { - emit_and(t2, S, brw_imm_uw(1)); /* S & 0b1 */ - emit_or(t1, t1, t2); /* (X & ~0b1) | (S & 0b1) */ - } - emit_shl(t1, t1, brw_imm_uw(1)); /* (X & ~0b1) << 1 - | (S & 0b1) << 1 */ - if (num_samples == 2) { - emit_mov(Yp, Y); - return; - } - - emit_and(t2, X, brw_imm_uw(1)); /* X & 0b1 */ - emit_or(Xp, t1, t2); - emit_and(t1, Y, brw_imm_uw(0xfffe)); /* Y & ~0b1 */ - emit_shl(t1, t1, brw_imm_uw(1)); /* (Y & ~0b1) << 1 */ - if (!s_is_zero) { - emit_and(t2, S, brw_imm_uw(2)); /* S & 0b10 */ - emit_or(t1, t1, t2); /* (Y & ~0b1) << 1 | (S & 0b10) */ - } - emit_and(t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ - emit_or(Yp, t1, t2); - break; - case 8: - /* encode_msaa(8, IMS, X, Y, S) = (X', Y', 0) - * where X' = (X & ~0b1) << 2 | (S & 0b100) | (S & 0b1) << 1 - * | (X & 0b1) - * Y' = (Y & ~0b1) << 1 | (S & 0b10) | (Y & 0b1) - */ - emit_and(t1, X, brw_imm_uw(0xfffe)); /* X & ~0b1 */ - emit_shl(t1, t1, brw_imm_uw(2)); /* (X & ~0b1) << 2 */ - if (!s_is_zero) { - emit_and(t2, S, brw_imm_uw(4)); /* S & 0b100 */ - emit_or(t1, t1, t2); /* (X & ~0b1) << 2 | (S & 0b100) */ - emit_and(t2, S, brw_imm_uw(1)); /* S & 0b1 */ - emit_shl(t2, t2, brw_imm_uw(1)); /* (S & 0b1) << 1 */ - emit_or(t1, t1, t2); /* (X & ~0b1) << 2 | (S & 0b100) - | (S & 0b1) << 1 */ - } - emit_and(t2, X, brw_imm_uw(1)); /* X & 0b1 */ - emit_or(Xp, t1, t2); - emit_and(t1, Y, brw_imm_uw(0xfffe)); /* Y & ~0b1 */ - emit_shl(t1, t1, brw_imm_uw(1)); /* (Y & ~0b1) << 1 */ - if (!s_is_zero) { - emit_and(t2, S, brw_imm_uw(2)); /* S & 0b10 */ - emit_or(t1, t1, t2); /* (Y & ~0b1) << 1 | (S & 0b10) */ - } - emit_and(t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ - emit_or(Yp, t1, t2); - break; - } - SWAP_XY_AND_XPYP(); - s_is_zero = true; - break; - } -} - -/** - * Emit code to compensate for the difference between MSAA and non-MSAA - * surfaces. - * - * This code modifies the X and Y coordinates according to the formula: - * - * (X', Y', S) = decode_msaa(num_samples, IMS, X, Y, S) - * - * (See brw_blorp_blit_program). - */ -void -brw_blorp_blit_program::decode_msaa(unsigned num_samples, - intel_msaa_layout layout) -{ - switch (layout) { - case INTEL_MSAA_LAYOUT_NONE: - /* No translation necessary, and S should already be zero. */ - assert(s_is_zero); - break; - case INTEL_MSAA_LAYOUT_CMS: - /* We can't compensate for compressed layout since at this point in the - * program we don't have access to the MCS buffer. - */ - unreachable("Bad layout in encode_msaa"); - case INTEL_MSAA_LAYOUT_UMS: - /* No translation necessary. */ - break; - case INTEL_MSAA_LAYOUT_IMS: - assert(s_is_zero); - switch (num_samples) { - case 2: - /* decode_msaa(2, IMS, X, Y, 0) = (X', Y', S) - * where X' = (X & ~0b11) >> 1 | (X & 0b1) - * S = (X & 0b10) >> 1 - */ - case 4: - /* decode_msaa(4, IMS, X, Y, 0) = (X', Y', S) - * where X' = (X & ~0b11) >> 1 | (X & 0b1) - * Y' = (Y & ~0b11) >> 1 | (Y & 0b1) - * S = (Y & 0b10) | (X & 0b10) >> 1 - */ - emit_and(t1, X, brw_imm_uw(0xfffc)); /* X & ~0b11 */ - emit_shr(t1, t1, brw_imm_uw(1)); /* (X & ~0b11) >> 1 */ - emit_and(t2, X, brw_imm_uw(1)); /* X & 0b1 */ - emit_or(Xp, t1, t2); - - if (num_samples == 2) { - emit_mov(Yp, Y); - emit_and(t2, X, brw_imm_uw(2)); /* X & 0b10 */ - emit_shr(S, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ - } else { - emit_and(t1, Y, brw_imm_uw(0xfffc)); /* Y & ~0b11 */ - emit_shr(t1, t1, brw_imm_uw(1)); /* (Y & ~0b11) >> 1 */ - emit_and(t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ - emit_or(Yp, t1, t2); - emit_and(t1, Y, brw_imm_uw(2)); /* Y & 0b10 */ - emit_and(t2, X, brw_imm_uw(2)); /* X & 0b10 */ - emit_shr(t2, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ - emit_or(S, t1, t2); - } - break; - case 8: - /* decode_msaa(8, IMS, X, Y, 0) = (X', Y', S) - * where X' = (X & ~0b111) >> 2 | (X & 0b1) - * Y' = (Y & ~0b11) >> 1 | (Y & 0b1) - * S = (X & 0b100) | (Y & 0b10) | (X & 0b10) >> 1 - */ - emit_and(t1, X, brw_imm_uw(0xfff8)); /* X & ~0b111 */ - emit_shr(t1, t1, brw_imm_uw(2)); /* (X & ~0b111) >> 2 */ - emit_and(t2, X, brw_imm_uw(1)); /* X & 0b1 */ - emit_or(Xp, t1, t2); - emit_and(t1, Y, brw_imm_uw(0xfffc)); /* Y & ~0b11 */ - emit_shr(t1, t1, brw_imm_uw(1)); /* (Y & ~0b11) >> 1 */ - emit_and(t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ - emit_or(Yp, t1, t2); - emit_and(t1, X, brw_imm_uw(4)); /* X & 0b100 */ - emit_and(t2, Y, brw_imm_uw(2)); /* Y & 0b10 */ - emit_or(t1, t1, t2); /* (X & 0b100) | (Y & 0b10) */ - emit_and(t2, X, brw_imm_uw(2)); /* X & 0b10 */ - emit_shr(t2, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ - emit_or(S, t1, t2); - break; - } - s_is_zero = false; - SWAP_XY_AND_XPYP(); - break; - } -} - -/** - * Emit code to translate from destination (X, Y) coordinates to source (X, Y) - * coordinates. - */ -void -brw_blorp_blit_program::translate_dst_to_src() -{ - struct brw_reg X_f = retype(X, BRW_REGISTER_TYPE_F); - struct brw_reg Y_f = retype(Y, BRW_REGISTER_TYPE_F); - struct brw_reg Xp_f = retype(Xp, BRW_REGISTER_TYPE_F); - struct brw_reg Yp_f = retype(Yp, BRW_REGISTER_TYPE_F); - - /* Move the UD coordinates to float registers. */ - emit_mov(Xp_f, X); - emit_mov(Yp_f, Y); - /* Scale and offset */ - emit_mad(X_f, x_transform.offset, Xp_f, x_transform.multiplier); - emit_mad(Y_f, y_transform.offset, Yp_f, y_transform.multiplier); - if (key->blit_scaled && key->blend) { - /* Translate coordinates to lay out the samples in a rectangular grid - * roughly corresponding to sample locations. - */ - emit_mul(X_f, X_f, brw_imm_f(key->x_scale)); - emit_mul(Y_f, Y_f, brw_imm_f(key->y_scale)); - /* Adjust coordinates so that integers represent pixel centers rather - * than pixel edges. - */ - emit_add(X_f, X_f, brw_imm_f(-0.5)); - emit_add(Y_f, Y_f, brw_imm_f(-0.5)); - - /* Clamp the X, Y texture coordinates to properly handle the sampling of - * texels on texture edges. - */ - clamp_tex_coords(X_f, Y_f, - brw_imm_f(0.0), brw_imm_f(0.0), - rect_grid_x1, rect_grid_y1); - - /* Store the fractional parts to be used as bilinear interpolation - * coefficients. - */ - emit_frc(x_frac, X_f); - emit_frc(y_frac, Y_f); - - /* Round the float coordinates down to nearest integer */ - emit_rndd(Xp_f, X_f); - emit_rndd(Yp_f, Y_f); - emit_mul(X_f, Xp_f, brw_imm_f(1.0f / key->x_scale)); - emit_mul(Y_f, Yp_f, brw_imm_f(1.0f / key->y_scale)); - SWAP_XY_AND_XPYP(); - } else if (!key->bilinear_filter) { - /* Round the float coordinates down to nearest integer by moving to - * UD registers. - */ - emit_mov(Xp, X_f); - emit_mov(Yp, Y_f); - SWAP_XY_AND_XPYP(); - } -} - -void -brw_blorp_blit_program::clamp_tex_coords(struct brw_reg regX, - struct brw_reg regY, - struct brw_reg clampX0, - struct brw_reg clampY0, - struct brw_reg clampX1, - struct brw_reg clampY1) -{ - emit_max(regX, regX, clampX0); - emit_max(regY, regY, clampY0); - emit_min(regX, regX, clampX1); - emit_min(regY, regY, clampY1); -} - - - -void -brw_blorp_blit_program::manual_blend_average(unsigned num_samples) -{ - if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) - mcs_fetch(); - - assert(key->texture_data_type == BRW_REGISTER_TYPE_F); - - /* We add together samples using a binary tree structure, e.g. for 4x MSAA: - * - * result = ((sample[0] + sample[1]) + (sample[2] + sample[3])) / 4 - * - * This ensures that when all samples have the same value, no numerical - * precision is lost, since each addition operation always adds two equal - * values, and summing two equal floating point values does not lose - * precision. - * - * We perform this computation by treating the texture_data array as a - * stack and performing the following operations: - * - * - push sample 0 onto stack - * - push sample 1 onto stack - * - add top two stack entries - * - push sample 2 onto stack - * - push sample 3 onto stack - * - add top two stack entries - * - add top two stack entries - * - divide top stack entry by 4 - * - * Note that after pushing sample i onto the stack, the number of add - * operations we do is equal to the number of trailing 1 bits in i. This - * works provided the total number of samples is a power of two, which it - * always is for i965. - * - * For integer formats, we replace the add operations with average - * operations and skip the final division. - */ - unsigned stack_depth = 0; - for (unsigned i = 0; i < num_samples; ++i) { - assert(stack_depth == _mesa_bitcount(i)); /* Loop invariant */ - - /* Push sample i onto the stack */ - assert(stack_depth < ARRAY_SIZE(texture_data)); - if (i == 0) { - s_is_zero = true; - } else { - s_is_zero = false; - emit_mov(vec16(S), brw_imm_ud(i)); - } - texel_fetch(texture_data[stack_depth++]); - - if (i == 0 && key->tex_layout == INTEL_MSAA_LAYOUT_CMS) { - /* The Ivy Bridge PRM, Vol4 Part1 p27 (Multisample Control Surface) - * suggests an optimization: - * - * "A simple optimization with probable large return in - * performance is to compare the MCS value to zero (indicating - * all samples are on sample slice 0), and sample only from - * sample slice 0 using ld2dss if MCS is zero." - * - * Note that in the case where the MCS value is zero, sampling from - * sample slice 0 using ld2dss and sampling from sample 0 using - * ld2dms are equivalent (since all samples are on sample slice 0). - * Since we have already sampled from sample 0, all we need to do is - * skip the remaining fetches and averaging if MCS is zero. - */ - emit_cmp_if(BRW_CONDITIONAL_NZ, mcs_data, brw_imm_ud(0)); - } - - /* Do count_trailing_one_bits(i) times */ - for (int j = count_trailing_one_bits(i); j-- > 0; ) { - assert(stack_depth >= 2); - --stack_depth; - - /* TODO: should use a smaller loop bound for non_RGBA formats */ - for (int k = 0; k < 4; ++k) { - emit_combine(BRW_OPCODE_ADD, - offset(texture_data[stack_depth - 1], 2*k), - offset(vec8(texture_data[stack_depth - 1]), 2*k), - offset(vec8(texture_data[stack_depth]), 2*k)); - } - } - } - - /* We should have just 1 sample on the stack now. */ - assert(stack_depth == 1); - - /* 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) { - emit_mul(offset(texture_data[0], 2*j), - offset(vec8(texture_data[0]), 2*j), - brw_imm_f(1.0f / num_samples)); - } - - if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) - emit_endif(); -} - -void -brw_blorp_blit_program::manual_blend_bilinear(unsigned num_samples) -{ - /* We do this computation by performing the following operations: - * - * In case of 4x, 8x MSAA: - * - Compute the pixel coordinates and sample numbers (a, b, c, d) - * which are later used for interpolation - * - linearly interpolate samples a and b in X - * - linearly interpolate samples c and d in X - * - linearly interpolate the results of last two operations in Y - * - * result = lrp(lrp(a + b) + lrp(c + d)) - */ - struct brw_reg Xp_f = retype(Xp, BRW_REGISTER_TYPE_F); - struct brw_reg Yp_f = retype(Yp, BRW_REGISTER_TYPE_F); - struct brw_reg t1_f = retype(t1, BRW_REGISTER_TYPE_F); - struct brw_reg t2_f = retype(t2, BRW_REGISTER_TYPE_F); - - for (unsigned i = 0; i < 4; ++i) { - assert(i < ARRAY_SIZE(texture_data)); - s_is_zero = false; - - /* Compute pixel coordinates */ - emit_add(vec16(x_sample_coords), Xp_f, - brw_imm_f((float)(i & 0x1) * (1.0f / key->x_scale))); - emit_add(vec16(y_sample_coords), Yp_f, - brw_imm_f((float)((i >> 1) & 0x1) * (1.0f / key->y_scale))); - emit_mov(vec16(X), x_sample_coords); - emit_mov(vec16(Y), y_sample_coords); - - /* The MCS value we fetch has to match up with the pixel that we're - * sampling from. Since we sample from different pixels in each - * iteration of this "for" loop, the call to mcs_fetch() should be - * here inside the loop after computing the pixel coordinates. - */ - if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) - mcs_fetch(); - - /* Compute sample index and map the sample index to a sample number. - * Sample index layout shows the numbering of slots in a rectangular - * grid of samples with in a pixel. Sample number layout shows the - * rectangular grid of samples roughly corresponding to the real sample - * locations with in a pixel. - * In case of 4x MSAA, layout of sample indices matches the layout of - * sample numbers: - * --------- - * | 0 | 1 | - * --------- - * | 2 | 3 | - * --------- - * - * In case of 8x MSAA the two layouts don't match. - * sample index layout : --------- sample number layout : --------- - * | 0 | 1 | | 5 | 2 | - * --------- --------- - * | 2 | 3 | | 4 | 6 | - * --------- --------- - * | 4 | 5 | | 0 | 3 | - * --------- --------- - * | 6 | 7 | | 7 | 1 | - * --------- --------- - * - * Fortunately, this can be done fairly easily as: - * S' = (0x17306425 >> (S * 4)) & 0xf - */ - emit_frc(vec16(t1_f), x_sample_coords); - emit_frc(vec16(t2_f), y_sample_coords); - emit_mul(vec16(t1_f), t1_f, brw_imm_f(key->x_scale)); - emit_mul(vec16(t2_f), t2_f, brw_imm_f(key->x_scale * key->y_scale)); - emit_add(vec16(t1_f), t1_f, t2_f); - emit_mov(vec16(S), t1_f); - - if (num_samples == 8) { - emit_mov(vec16(t2), brw_imm_d(0x17306425)); - emit_shl(vec16(S), S, brw_imm_d(2)); - emit_shr(vec16(S), t2, S); - emit_and(vec16(S), S, brw_imm_d(0xf)); - } - texel_fetch(texture_data[i]); - } - -#define SAMPLE(x, y) offset(texture_data[x], y) - for (int index = 3; index > 0; ) { - /* Since we're doing SIMD16, 4 color channels fits in to 8 registers. - * Counter value of 8 in 'for' loop below is used to interpolate all - * the color components. - */ - for (int k = 0; k < 8; k += 2) - emit_lrp(vec8(SAMPLE(index - 1, k)), - x_frac, - vec8(SAMPLE(index, k)), - vec8(SAMPLE(index - 1, k))); - index -= 2; - } - for (int k = 0; k < 8; k += 2) - emit_lrp(vec8(SAMPLE(0, k)), - y_frac, - vec8(SAMPLE(2, k)), - vec8(SAMPLE(0, k))); -#undef SAMPLE -} - -/** - * 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(struct brw_reg dst) -{ - static const sampler_message_arg args[2] = { - SAMPLER_MESSAGE_ARG_U_FLOAT, - SAMPLER_MESSAGE_ARG_V_FLOAT - }; - - texture_lookup(dst, SHADER_OPCODE_TEX, args, ARRAY_SIZE(args)); -} - -/** - * Emit code to look up a value in the texture using the SAMPLE_LD message - * (which does a simple texel fetch). - */ -void -brw_blorp_blit_program::texel_fetch(struct brw_reg dst) -{ - static const sampler_message_arg gen6_args[5] = { - SAMPLER_MESSAGE_ARG_U_INT, - SAMPLER_MESSAGE_ARG_V_INT, - SAMPLER_MESSAGE_ARG_ZERO_INT, /* R */ - SAMPLER_MESSAGE_ARG_ZERO_INT, /* LOD */ - SAMPLER_MESSAGE_ARG_SI_INT - }; - static const sampler_message_arg gen7_ld_args[] = { - SAMPLER_MESSAGE_ARG_U_INT, - SAMPLER_MESSAGE_ARG_ZERO_INT, /* LOD */ - SAMPLER_MESSAGE_ARG_V_INT, - SAMPLER_MESSAGE_ARG_R_INT - }; - static const sampler_message_arg gen7_ld2dss_args[3] = { - SAMPLER_MESSAGE_ARG_SI_INT, - SAMPLER_MESSAGE_ARG_U_INT, - SAMPLER_MESSAGE_ARG_V_INT - }; - static const sampler_message_arg gen7_ld2dms_args[4] = { - SAMPLER_MESSAGE_ARG_SI_INT, - SAMPLER_MESSAGE_ARG_MCS_INT, - SAMPLER_MESSAGE_ARG_U_INT, - SAMPLER_MESSAGE_ARG_V_INT - }; - static const sampler_message_arg gen9_ld_args[] = { - SAMPLER_MESSAGE_ARG_U_INT, - SAMPLER_MESSAGE_ARG_V_INT, - SAMPLER_MESSAGE_ARG_ZERO_INT, /* LOD */ - SAMPLER_MESSAGE_ARG_R_INT - }; - - switch (brw->gen) { - case 6: - texture_lookup(dst, SHADER_OPCODE_TXF, gen6_args, s_is_zero ? 2 : 5); - break; - case 7: - case 8: - case 9: - switch (key->tex_layout) { - case INTEL_MSAA_LAYOUT_IMS: - /* From the Ivy Bridge PRM, Vol4 Part1 p72 (Multisampled Surface Storage - * Format): - * - * If this field is MSFMT_DEPTH_STENCIL - * [a.k.a. INTEL_MSAA_LAYOUT_IMS], the only sampling engine - * messages allowed are "ld2dms", "resinfo", and "sampleinfo". - * - * So fall through to emit the same message as we use for - * INTEL_MSAA_LAYOUT_CMS. - */ - case INTEL_MSAA_LAYOUT_CMS: - texture_lookup(dst, SHADER_OPCODE_TXF_CMS, - gen7_ld2dms_args, ARRAY_SIZE(gen7_ld2dms_args)); - break; - case INTEL_MSAA_LAYOUT_UMS: - texture_lookup(dst, SHADER_OPCODE_TXF_UMS, - gen7_ld2dss_args, ARRAY_SIZE(gen7_ld2dss_args)); - break; - case INTEL_MSAA_LAYOUT_NONE: - assert(s_is_zero); - if (brw->gen < 9) { - texture_lookup(dst, SHADER_OPCODE_TXF, gen7_ld_args, - ARRAY_SIZE(gen7_ld_args)); - } else { - texture_lookup(dst, SHADER_OPCODE_TXF, gen9_ld_args, - ARRAY_SIZE(gen9_ld_args)); - } - break; - } - break; - default: - unreachable("Should not get here."); - }; -} - -void -brw_blorp_blit_program::mcs_fetch() -{ - static const sampler_message_arg gen7_ld_mcs_args[2] = { - SAMPLER_MESSAGE_ARG_U_INT, - SAMPLER_MESSAGE_ARG_V_INT - }; - texture_lookup(vec16(mcs_data), SHADER_OPCODE_TXF_MCS, - gen7_ld_mcs_args, ARRAY_SIZE(gen7_ld_mcs_args)); -} - -void -brw_blorp_blit_program::texture_lookup(struct brw_reg dst, - enum opcode op, - const sampler_message_arg *args, - int num_args) -{ - struct brw_reg mrf = - retype(vec16(brw_message_reg(base_mrf)), BRW_REGISTER_TYPE_UD); - for (int arg = 0; arg < num_args; ++arg) { - switch (args[arg]) { - case SAMPLER_MESSAGE_ARG_U_FLOAT: - if (key->bilinear_filter) - emit_mov(retype(mrf, BRW_REGISTER_TYPE_F), - retype(X, BRW_REGISTER_TYPE_F)); - else - emit_mov(retype(mrf, BRW_REGISTER_TYPE_F), X); - break; - case SAMPLER_MESSAGE_ARG_V_FLOAT: - if (key->bilinear_filter) - emit_mov(retype(mrf, BRW_REGISTER_TYPE_F), - retype(Y, BRW_REGISTER_TYPE_F)); - else - emit_mov(retype(mrf, BRW_REGISTER_TYPE_F), Y); - break; - case SAMPLER_MESSAGE_ARG_U_INT: - emit_mov(mrf, X); - break; - case SAMPLER_MESSAGE_ARG_V_INT: - emit_mov(mrf, Y); - break; - case SAMPLER_MESSAGE_ARG_R_INT: - emit_mov(mrf, src_z); - break; - case SAMPLER_MESSAGE_ARG_SI_INT: - /* Note: on Gen7, this code may be reached with s_is_zero==true - * because in Gen7's ld2dss message, the sample index is the first - * argument. When this happens, we need to move a 0 into the - * appropriate message register. - */ - if (s_is_zero) - emit_mov(mrf, brw_imm_ud(0)); - else - emit_mov(mrf, S); - break; - case SAMPLER_MESSAGE_ARG_MCS_INT: - switch (key->tex_layout) { - case INTEL_MSAA_LAYOUT_CMS: - emit_mov(mrf, mcs_data); - break; - case INTEL_MSAA_LAYOUT_IMS: - /* When sampling from an IMS surface, MCS data is not relevant, - * and the hardware ignores it. So don't bother populating it. - */ - break; - default: - /* We shouldn't be trying to send MCS data with any other - * layouts. - */ - assert (!"Unsupported layout for MCS data"); - break; - } - break; - case SAMPLER_MESSAGE_ARG_ZERO_INT: - emit_mov(mrf, brw_imm_ud(0)); - break; - } - mrf.nr += 2; - } - - emit_texture_lookup(retype(dst, BRW_REGISTER_TYPE_UW) /* dest */, - op, - base_mrf, - mrf.nr - base_mrf /* msg_length */); -} - -#undef X -#undef Y -#undef U -#undef V -#undef S -#undef SWAP_XY_AND_XPYP - static void brw_blorp_get_blit_kernel(struct brw_context *brw, struct brw_blorp_params *params, @@ -2684,20 +1453,14 @@ brw_blorp_get_blit_kernel(struct brw_context *brw, * method of building shaders manually. */ nir_shader *nir = brw_blorp_build_nir_shader(brw, prog_key, &prog_data); - if (nir) { - struct brw_wm_prog_key wm_key; - brw_blorp_init_wm_prog_key(&wm_key); - wm_key.tex.compressed_multisample_layout_mask = - prog_key->tex_layout == INTEL_MSAA_LAYOUT_CMS; - wm_key.multisample_fbo = prog_key->rt_samples > 1; - - program = brw_blorp_compile_nir_shader(brw, nir, &wm_key, false, - &prog_data, &program_size); - } else { - brw_blorp_blit_program prog(brw, prog_key); - program = prog.compile(brw, INTEL_DEBUG & DEBUG_BLORP, &program_size); - prog_data = prog.prog_data; - } + struct brw_wm_prog_key wm_key; + brw_blorp_init_wm_prog_key(&wm_key); + wm_key.tex.compressed_multisample_layout_mask = + prog_key->tex_layout == INTEL_MSAA_LAYOUT_CMS; + wm_key.multisample_fbo = prog_key->rt_samples > 1; + + program = brw_blorp_compile_nir_shader(brw, nir, &wm_key, false, + &prog_data, &program_size); brw_upload_cache(&brw->cache, BRW_CACHE_BLORP_PROG, prog_key, sizeof(*prog_key), @@ -2706,41 +1469,6 @@ brw_blorp_get_blit_kernel(struct brw_context *brw, ¶ms->wm_prog_kernel, ¶ms->wm_prog_data); } -void -brw_blorp_blit_program::render_target_write() -{ - struct brw_reg mrf_rt_write = - retype(vec16(brw_message_reg(base_mrf)), key->texture_data_type); - int mrf_offset = 0; - - /* If we may have killed pixels, then we need to send R0 and R1 in a header - * so that the render target knows which pixels we killed. - */ - bool use_header = key->use_kill; - if (use_header) { - /* Copy R0/1 to MRF */ - emit_mov(retype(mrf_rt_write, BRW_REGISTER_TYPE_UD), - retype(R0, BRW_REGISTER_TYPE_UD)); - mrf_offset += 2; - } - - /* 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 } */ - emit_mov(offset(mrf_rt_write, mrf_offset), - offset(vec8(texture_data[0]), 2*i)); - mrf_offset += 2; - } - - /* Now write to the render target and terminate the thread */ - emit_render_target_write( - mrf_rt_write, - brw->gen < 8 ? base_mrf : -1, - mrf_offset /* msg_length. TODO: Should be smaller for non-RGBA formats. */, - use_header); -} - - static void brw_blorp_setup_coord_transform(struct brw_blorp_coord_transform *xform, GLfloat src0, GLfloat src1, diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit_eu.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit_eu.cpp deleted file mode 100644 index 99b4ff5d667..00000000000 --- a/src/mesa/drivers/dri/i965/brw_blorp_blit_eu.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright © 2013 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 "util/ralloc.h" -#include "brw_blorp_blit_eu.h" -#include "brw_blorp.h" -#include "brw_cfg.h" - -brw_blorp_eu_emitter::brw_blorp_eu_emitter() - : mem_ctx(ralloc_context(NULL)) -{ -} - -brw_blorp_eu_emitter::~brw_blorp_eu_emitter() -{ - ralloc_free(mem_ctx); -} - -const unsigned * -brw_blorp_eu_emitter::get_program(struct brw_context *brw, bool debug_flag, - unsigned *program_size) -{ - cfg_t cfg(&insts); - brw_stage_prog_data prog_data = { 0 }; - brw_wm_prog_key prog_key = { 0 }; - - prog_data.binding_table.texture_start = - BRW_BLORP_TEXTURE_BINDING_TABLE_INDEX; - - fs_generator generator(brw->intelScreen->compiler, brw, mem_ctx, &prog_key, - &prog_data, 0, false, MESA_SHADER_FRAGMENT); - - if (debug_flag) - generator.enable_debug("blorp"); - - generator.generate_code(&cfg, 16); - - return generator.get_assembly(program_size); -} - -/** - * Emit code that kills pixels whose X and Y coordinates are outside the - * boundary of the rectangle defined by the push constants (dst_x0, dst_y0, - * dst_x1, dst_y1). - */ -void -brw_blorp_eu_emitter::emit_kill_if_outside_rect(const struct brw_reg &x, - const struct brw_reg &y, - const struct brw_reg &dst_x0, - const struct brw_reg &dst_x1, - const struct brw_reg &dst_y0, - const struct brw_reg &dst_y1) -{ - struct brw_reg f0 = brw_flag_reg(0, 0); - struct brw_reg g1 = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW); - - emit_cmp(BRW_CONDITIONAL_GE, x, dst_x0); - emit_cmp(BRW_CONDITIONAL_GE, y, dst_y0)->predicate = BRW_PREDICATE_NORMAL; - emit_cmp(BRW_CONDITIONAL_L, x, dst_x1)->predicate = BRW_PREDICATE_NORMAL; - emit_cmp(BRW_CONDITIONAL_L, y, dst_y1)->predicate = BRW_PREDICATE_NORMAL; - - fs_inst *inst = new (mem_ctx) fs_inst(BRW_OPCODE_AND, 16, g1, f0, g1); - inst->force_writemask_all = true; - insts.push_tail(inst); -} - -void -brw_blorp_eu_emitter::emit_texture_lookup(const struct brw_reg &dst, - enum opcode op, - unsigned base_mrf, - unsigned msg_length) -{ - fs_inst *inst = new (mem_ctx) fs_inst(op, 16, dst, brw_message_reg(base_mrf), - brw_imm_ud(0u), brw_imm_ud(0u)); - - inst->base_mrf = base_mrf; - inst->mlen = msg_length; - inst->header_size = 0; - inst->regs_written = 8; - - insts.push_tail(inst); -} - -void -brw_blorp_eu_emitter::emit_render_target_write(const struct brw_reg &src0, - int msg_reg_nr, - unsigned msg_length, - bool use_header) -{ - fs_inst *inst = new (mem_ctx) fs_inst(FS_OPCODE_BLORP_FB_WRITE, 16); - - inst->src[0] = src0; - inst->sources = 1; - inst->base_mrf = msg_reg_nr; - inst->mlen = msg_length; - inst->header_size = use_header ? 2 : 0; - inst->target = BRW_BLORP_RENDERBUFFER_BINDING_TABLE_INDEX; - - insts.push_tail(inst); -} - -void -brw_blorp_eu_emitter::emit_combine(enum opcode combine_opcode, - const struct brw_reg &dst, - const struct brw_reg &src_1, - const struct brw_reg &src_2) -{ - assert(combine_opcode == BRW_OPCODE_ADD || combine_opcode == BRW_OPCODE_AVG); - - insts.push_tail(new (mem_ctx) fs_inst(combine_opcode, 16, dst, - src_1, src_2)); -} - -fs_inst * -brw_blorp_eu_emitter::emit_cmp(enum brw_conditional_mod op, - const struct brw_reg &x, - const struct brw_reg &y) -{ - fs_inst *cmp = new (mem_ctx) fs_inst(BRW_OPCODE_CMP, 16, - vec16(brw_null_reg()), x, y); - cmp->conditional_mod = op; - insts.push_tail(cmp); - return cmp; -} - diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit_eu.h b/src/mesa/drivers/dri/i965/brw_blorp_blit_eu.h deleted file mode 100644 index e2b99ddc821..00000000000 --- a/src/mesa/drivers/dri/i965/brw_blorp_blit_eu.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright © 2013 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. - */ - -#ifndef BRW_BLORP_BLIT_EU_H -#define BRW_BLORP_BLIT_EU_H - -#include "brw_fs.h" - -class brw_blorp_eu_emitter -{ -protected: - brw_blorp_eu_emitter(); - ~brw_blorp_eu_emitter(); - - const unsigned *get_program(struct brw_context *brw, bool debug_flag, - unsigned *program_size); - - void emit_kill_if_outside_rect(const struct brw_reg &x, - const struct brw_reg &y, - const struct brw_reg &dst_x0, - const struct brw_reg &dst_x1, - const struct brw_reg &dst_y0, - const struct brw_reg &dst_y1); - - void emit_texture_lookup(const struct brw_reg &dst, - enum opcode op, - unsigned base_mrf, - unsigned msg_length); - - void emit_render_target_write(const struct brw_reg &src0, - int msg_reg_nr, - unsigned msg_length, - bool use_header); - - void emit_combine(enum opcode combine_opcode, - const struct brw_reg &dst, - const struct brw_reg &src_1, - const struct brw_reg &src_2); - - inline void emit_cond_mov(const struct brw_reg &x, - const struct brw_reg &y, - enum brw_conditional_mod op, - const struct brw_reg &dst, - const struct brw_reg &src) - { - emit_cmp(op, x, y); - - fs_inst *mv = new (mem_ctx) fs_inst(BRW_OPCODE_MOV, 16, dst, src); - mv->predicate = BRW_PREDICATE_NORMAL; - insts.push_tail(mv); - } - - inline void emit_if_eq_mov(const struct brw_reg &x, unsigned y, - const struct brw_reg &dst, unsigned src) - { - emit_cond_mov(x, brw_imm_d(y), BRW_CONDITIONAL_EQ, dst, brw_imm_d(src)); - } - - inline void emit_lrp(const struct brw_reg &dst, - const struct brw_reg &src1, - const struct brw_reg &src2, - const struct brw_reg &src3) - { - insts.push_tail( - new (mem_ctx) fs_inst(BRW_OPCODE_LRP, 16, dst, src1, src2, src3)); - } - - inline void emit_mad(const struct brw_reg &dst, - const struct brw_reg &src1, - const struct brw_reg &src2, - const struct brw_reg &src3) - { - insts.push_tail( - new (mem_ctx) fs_inst(BRW_OPCODE_MAD, 16, dst, src1, src2, src3)); - } - - inline void emit_min(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - fs_inst *inst = new (mem_ctx) fs_inst(BRW_OPCODE_SEL, 16, dst, src1, src2); - inst->conditional_mod = BRW_CONDITIONAL_L; - insts.push_tail(inst); - } - - inline void emit_max(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - fs_inst *inst = new (mem_ctx) fs_inst(BRW_OPCODE_SEL, 16, dst, src1, src2); - inst->conditional_mod = BRW_CONDITIONAL_GE; - insts.push_tail(inst); - } - - inline void emit_mov(const struct brw_reg& dst, const struct brw_reg& src) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_MOV, 16, dst, src)); - } - - inline void emit_mov_8(const struct brw_reg& dst, const struct brw_reg& src) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_MOV, 8, dst, src)); - } - - inline void emit_and(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_AND, 16, dst, src1, src2)); - } - - inline void emit_add(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_ADD, 16, dst, src1, src2)); - } - - inline void emit_add_8(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_ADD, 8, dst, src1, src2)); - } - - inline void emit_mul(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_MUL, 16, dst, src1, src2)); - } - - inline void emit_shr(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_SHR, 16, dst, src1, src2)); - } - - inline void emit_shl(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_SHL, 16, dst, src1, src2)); - } - - inline void emit_or(const struct brw_reg& dst, - const struct brw_reg& src1, - const struct brw_reg& src2) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_OR, 16, dst, src1, src2)); - } - - inline void emit_frc(const struct brw_reg& dst, - const struct brw_reg& src) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_FRC, 16, dst, src)); - } - - inline void emit_rndd(const struct brw_reg& dst, - const struct brw_reg& src) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_RNDD, 16, dst, src)); - } - - inline void emit_cmp_if(enum brw_conditional_mod op, - const struct brw_reg &x, - const struct brw_reg &y) - { - emit_cmp(op, x, y); - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_IF, 16)); - } - - inline void emit_else(void) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_ELSE, 16)); - } - - inline void emit_endif(void) - { - insts.push_tail(new (mem_ctx) fs_inst(BRW_OPCODE_ENDIF, 16)); - } - -private: - fs_inst *emit_cmp(enum brw_conditional_mod op, const struct brw_reg &x, - const struct brw_reg &y); - - void *mem_ctx; - exec_list insts; -}; - -#endif /* BRW_BLORP_BLIT_EU_H */ diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index fce510c8fe0..3395c9b87cc 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -950,7 +950,6 @@ enum opcode { */ FS_OPCODE_FB_WRITE_LOGICAL, - FS_OPCODE_BLORP_FB_WRITE, FS_OPCODE_REP_FB_WRITE, FS_OPCODE_PACK_STENCIL_REF, SHADER_OPCODE_RCP, diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index b906f3d0a5f..d4eb8fb7be4 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -437,7 +437,6 @@ private: void generate_stencil_ref_packing(fs_inst *inst, struct brw_reg dst, struct brw_reg src); void generate_barrier(fs_inst *inst, struct brw_reg src); - void generate_blorp_fb_write(fs_inst *inst, struct brw_reg payload); void generate_linterp(fs_inst *inst, struct brw_reg dst, struct brw_reg *src); void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src, diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp index 3b50a82f94e..fd2ae963f6a 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp @@ -556,23 +556,6 @@ fs_generator::generate_barrier(fs_inst *inst, struct brw_reg src) } void -fs_generator::generate_blorp_fb_write(fs_inst *inst, struct brw_reg payload) -{ - brw_fb_WRITE(p, - 16 /* dispatch_width */, - inst->base_mrf >= 0 ? - brw_message_reg(inst->base_mrf) : payload, - brw_null_reg(), - BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, - inst->target, - inst->mlen, - 0, - true, - true, - inst->header_size != 0); -} - -void fs_generator::generate_linterp(fs_inst *inst, struct brw_reg dst, struct brw_reg *src) { @@ -2211,10 +2194,6 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width) generate_fb_write(inst, src[0]); break; - case FS_OPCODE_BLORP_FB_WRITE: - generate_blorp_fb_write(inst, src[0]); - break; - case FS_OPCODE_MOV_DISPATCH_TO_FLAGS: generate_mov_dispatch_to_flags(inst); break; diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 48828df4c8e..50df979eff1 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -182,8 +182,6 @@ brw_instruction_name(const struct brw_device_info *devinfo, enum opcode op) return "fb_write_logical"; case FS_OPCODE_PACK_STENCIL_REF: return "pack_stencil_ref"; - case FS_OPCODE_BLORP_FB_WRITE: - return "blorp_fb_write"; case FS_OPCODE_REP_FB_WRITE: return "rep_fb_write"; |