static bool lower_offset(nir_builder *b, nir_tex_instr *tex) { int offset_index = nir_tex_instr_src_index(tex, nir_tex_src_offset); if (offset_index < 0) return false; int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord); assert(coord_index >= 0); assert(tex->src[offset_index].src.is_ssa); assert(tex->src[coord_index].src.is_ssa); nir_ssa_def *offset = tex->src[offset_index].src.ssa; nir_ssa_def *coord = tex->src[coord_index].src.ssa; b->cursor = nir_before_instr(&tex->instr); nir_ssa_def *offset_coord; if (nir_tex_instr_src_type(tex, coord_index) == nir_type_float) { if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) { offset_coord = nir_fadd(b, coord, nir_i2f32(b, offset)); } else { nir_ssa_def *txs = get_texture_size(b, tex); nir_ssa_def *scale = nir_frcp(b, txs); offset_coord = nir_fadd(b, coord, nir_fmul(b, nir_i2f32(b, offset), scale)); } } else { offset_coord = nir_iadd(b, coord, offset); } if (tex->is_array) { /* The offset is not applied to the array index */ if (tex->coord_components == 2) { offset_coord = nir_vec2(b, nir_channel(b, offset_coord, 0), nir_channel(b, coord, 1)); } else if (tex->coord_components == 3) { offset_coord = nir_vec3(b, nir_channel(b, offset_coord, 0), nir_channel(b, offset_coord, 1), nir_channel(b, coord, 2)); } else { unreachable("Invalid number of components"); } } nir_instr_rewrite_src(&tex->instr, &tex->src[coord_index].src, nir_src_for_ssa(offset_coord)); nir_tex_instr_remove_src(tex, offset_index); return true; }
/* Multiply interp_var_at_offset's offset by transform.x to flip it. */ static void lower_interp_var_at_offset(lower_wpos_ytransform_state *state, nir_intrinsic_instr *interp) { nir_builder *b = &state->b; nir_ssa_def *offset; nir_ssa_def *flip_y; b->cursor = nir_before_instr(&interp->instr); offset = nir_ssa_for_src(b, interp->src[0], 2); flip_y = nir_fmul(b, nir_channel(b, offset, 1), nir_channel(b, get_transform(state), 0)); nir_instr_rewrite_src(&interp->instr, &interp->src[0], nir_src_for_ssa(nir_vec2(b, nir_channel(b, offset, 0), flip_y))); }
static void lower_load_sample_pos(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) { nir_builder *b = &state->b; b->cursor = nir_after_instr(&intr->instr); nir_ssa_def *pos = &intr->dest.ssa; nir_ssa_def *scale = nir_channel(b, get_transform(state), 0); nir_ssa_def *neg_scale = nir_channel(b, get_transform(state), 2); /* Either y or 1-y for scale equal to 1 or -1 respectively. */ nir_ssa_def *flipped_y = nir_fadd(b, nir_fmax(b, neg_scale, nir_imm_float(b, 0.0)), nir_fmul(b, nir_channel(b, pos, 1), scale)); nir_ssa_def *flipped_pos = nir_vec2(b, nir_channel(b, pos, 0), flipped_y); nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pos), flipped_pos->parent_instr); }
static void lower_load_pointcoord(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr) { nir_builder *b = &state->b; b->cursor = nir_after_instr(&intr->instr); nir_ssa_def *pntc = &intr->dest.ssa; nir_ssa_def *transform = get_transform(state); nir_ssa_def *y = nir_channel(b, pntc, 1); /* The offset is 1 if we're flipping, 0 otherwise. */ nir_ssa_def *offset = nir_fmax(b, nir_channel(b, transform, 2), nir_imm_float(b, 0.0)); /* Flip the sign of y if we're flipping. */ nir_ssa_def *scaled = nir_fmul(b, y, nir_channel(b, transform, 0)); /* Reassemble the vector. */ nir_ssa_def *flipped_pntc = nir_vec2(b, nir_channel(b, pntc, 0), nir_fadd(b, offset, scaled)); nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pntc), flipped_pntc->parent_instr); }
static void project_src(nir_builder *b, nir_tex_instr *tex) { /* Find the projector in the srcs list, if present. */ int proj_index = nir_tex_instr_src_index(tex, nir_tex_src_projector); if (proj_index < 0) return; b->cursor = nir_before_instr(&tex->instr); nir_ssa_def *inv_proj = nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1)); /* Walk through the sources projecting the arguments. */ for (unsigned i = 0; i < tex->num_srcs; i++) { switch (tex->src[i].src_type) { case nir_tex_src_coord: case nir_tex_src_comparator: break; default: continue; } nir_ssa_def *unprojected = nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i)); nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj); /* Array indices don't get projected, so make an new vector with the * coordinate's array index untouched. */ if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) { switch (tex->coord_components) { case 4: projected = nir_vec4(b, nir_channel(b, projected, 0), nir_channel(b, projected, 1), nir_channel(b, projected, 2), nir_channel(b, unprojected, 3)); break; case 3: projected = nir_vec3(b, nir_channel(b, projected, 0), nir_channel(b, projected, 1), nir_channel(b, unprojected, 2)); break; case 2: projected = nir_vec2(b, nir_channel(b, projected, 0), nir_channel(b, unprojected, 1)); break; default: unreachable("bad texture coord count for array"); break; } } nir_instr_rewrite_src(&tex->instr, &tex->src[i].src, nir_src_for_ssa(projected)); } nir_tex_instr_remove_src(tex, proj_index); }
static void vc4_nir_lower_txf_ms_instr(struct vc4_compile *c, nir_builder *b, nir_tex_instr *txf_ms) { if (txf_ms->op != nir_texop_txf_ms) return; b->cursor = nir_before_instr(&txf_ms->instr); nir_tex_instr *txf = nir_tex_instr_create(c->s, 1); txf->op = nir_texop_txf; txf->sampler = txf_ms->sampler; txf->sampler_index = txf_ms->sampler_index; txf->coord_components = txf_ms->coord_components; txf->is_shadow = txf_ms->is_shadow; txf->is_new_style_shadow = txf_ms->is_new_style_shadow; nir_ssa_def *coord = NULL, *sample_index = NULL; for (int i = 0; i < txf_ms->num_srcs; i++) { assert(txf_ms->src[i].src.is_ssa); switch (txf_ms->src[i].src_type) { case nir_tex_src_coord: coord = txf_ms->src[i].src.ssa; break; case nir_tex_src_ms_index: sample_index = txf_ms->src[i].src.ssa; break; default: unreachable("Unknown txf_ms src\n"); } } assert(coord); assert(sample_index); nir_ssa_def *x = nir_channel(b, coord, 0); nir_ssa_def *y = nir_channel(b, coord, 1); uint32_t tile_w = 32; uint32_t tile_h = 32; uint32_t tile_w_shift = 5; uint32_t tile_h_shift = 5; uint32_t tile_size = (tile_h * tile_w * VC4_MAX_SAMPLES * sizeof(uint32_t)); unsigned unit = txf_ms->sampler_index; uint32_t w = align(c->key->tex[unit].msaa_width, tile_w); uint32_t w_tiles = w / tile_w; nir_ssa_def *x_tile = nir_ushr(b, x, nir_imm_int(b, tile_w_shift)); nir_ssa_def *y_tile = nir_ushr(b, y, nir_imm_int(b, tile_h_shift)); nir_ssa_def *tile_addr = nir_iadd(b, nir_imul(b, x_tile, nir_imm_int(b, tile_size)), nir_imul(b, y_tile, nir_imm_int(b, (w_tiles * tile_size)))); nir_ssa_def *x_subspan = nir_iand(b, x, nir_imm_int(b, (tile_w - 1) & ~1)); nir_ssa_def *y_subspan = nir_iand(b, y, nir_imm_int(b, (tile_h - 1) & ~1)); nir_ssa_def *subspan_addr = nir_iadd(b, nir_imul(b, x_subspan, nir_imm_int(b, 2 * VC4_MAX_SAMPLES * sizeof(uint32_t))), nir_imul(b, y_subspan, nir_imm_int(b, tile_w * VC4_MAX_SAMPLES * sizeof(uint32_t)))); nir_ssa_def *pixel_addr = nir_ior(b, nir_iand(b, nir_ishl(b, x, nir_imm_int(b, 2)), nir_imm_int(b, (1 << 2))), nir_iand(b, nir_ishl(b, y, nir_imm_int(b, 3)), nir_imm_int(b, (1 << 3)))); nir_ssa_def *sample_addr = nir_ishl(b, sample_index, nir_imm_int(b, 4)); nir_ssa_def *addr = nir_iadd(b, nir_ior(b, sample_addr, pixel_addr), nir_iadd(b, subspan_addr, tile_addr)); txf->src[0].src_type = nir_tex_src_coord; txf->src[0].src = nir_src_for_ssa(nir_vec2(b, addr, nir_imm_int(b, 0))); nir_ssa_dest_init(&txf->instr, &txf->dest, 4, NULL); nir_builder_instr_insert(b, &txf->instr); nir_ssa_def_rewrite_uses(&txf_ms->dest.ssa, nir_src_for_ssa(&txf->dest.ssa)); nir_instr_remove(&txf_ms->instr); }