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 convert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *y, nir_ssa_def *u, nir_ssa_def *v, nir_ssa_def *a) { nir_const_value m[3][4] = { { { .f32 = 1.16438356f }, { .f32 = 1.16438356f }, { .f32 = 1.16438356f }, { .f32 = 0.0f } }, { { .f32 = 0.0f }, { .f32 = -0.39176229f }, { .f32 = 2.01723214f }, { .f32 = 0.0f } }, { { .f32 = 1.59602678f }, { .f32 = -0.81296764f }, { .f32 = 0.0f }, { .f32 = 0.0f } }, }; nir_ssa_def *offset = nir_vec4(b, nir_imm_float(b, -0.874202214f), nir_imm_float(b, 0.531667820f), nir_imm_float(b, -1.085630787f), a); nir_ssa_def *result = nir_ffma(b, y, nir_build_imm(b, 4, 32, m[0]), nir_ffma(b, u, nir_build_imm(b, 4, 32, m[1]), nir_ffma(b, v, nir_build_imm(b, 4, 32, m[2]), offset))); nir_ssa_def_rewrite_uses(&tex->dest.ssa, nir_src_for_ssa(result)); } static void lower_y_uv_external(nir_builder *b, nir_tex_instr *tex, const nir_lower_tex_options *options)
} static void convert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *y, nir_ssa_def *u, nir_ssa_def *v) { nir_const_value m[3] = { { .f32 = { 1.0f, 0.0f, 1.59602678f, 0.0f } }, { .f32 = { 1.0f, -0.39176229f, -0.81296764f, 0.0f } }, { .f32 = { 1.0f, 2.01723214f, 0.0f, 0.0f } } }; nir_ssa_def *yuv = nir_vec4(b, nir_fmul(b, nir_imm_float(b, 1.16438356f), nir_fadd(b, y, nir_imm_float(b, -0.0625f))), nir_channel(b, nir_fadd(b, u, nir_imm_float(b, -0.5f)), 0), nir_channel(b, nir_fadd(b, v, nir_imm_float(b, -0.5f)), 0), nir_imm_float(b, 0.0)); nir_ssa_def *red = nir_fdot4(b, yuv, nir_build_imm(b, 4, 32, m[0])); nir_ssa_def *green = nir_fdot4(b, yuv, nir_build_imm(b, 4, 32, m[1])); nir_ssa_def *blue = nir_fdot4(b, yuv, nir_build_imm(b, 4, 32, m[2])); nir_ssa_def *result = nir_vec4(b, red, green, blue, nir_imm_float(b, 1.0f)); nir_ssa_def_rewrite_uses(&tex->dest.ssa, nir_src_for_ssa(result)); } static void lower_y_uv_external(nir_builder *b, nir_tex_instr *tex) {
/* see emit_wpos_adjustment() in st_mesa_to_tgsi.c */ static void emit_wpos_adjustment(lower_wpos_ytransform_state *state, nir_intrinsic_instr *intr, bool invert, float adjX, float adjY[2]) { nir_builder *b = &state->b; nir_variable *fragcoord = intr->variables[0]->var; nir_ssa_def *wpostrans, *wpos_temp, *wpos_temp_y, *wpos_input; assert(intr->dest.is_ssa); b->cursor = nir_before_instr(&intr->instr); wpostrans = get_transform(state); wpos_input = nir_load_var(b, fragcoord); /* First, apply the coordinate shift: */ if (adjX || adjY[0] || adjY[1]) { if (adjY[0] != adjY[1]) { /* Adjust the y coordinate by adjY[1] or adjY[0] respectively * depending on whether inversion is actually going to be applied * or not, which is determined by testing against the inversion * state variable used below, which will be either +1 or -1. */ nir_ssa_def *adj_temp; adj_temp = nir_cmp(b, nir_channel(b, wpostrans, invert ? 2 : 0), nir_imm_vec4(b, adjX, adjY[0], 0.0f, 0.0f), nir_imm_vec4(b, adjX, adjY[1], 0.0f, 0.0f)); wpos_temp = nir_fadd(b, wpos_input, adj_temp); } else { wpos_temp = nir_fadd(b, wpos_input, nir_imm_vec4(b, adjX, adjY[0], 0.0f, 0.0f)); } wpos_input = wpos_temp; } else { /* MOV wpos_temp, input[wpos] */ wpos_temp = wpos_input; } /* Now the conditional y flip: STATE_FB_WPOS_Y_TRANSFORM.xy/zw will be * inversion/identity, or the other way around if we're drawing to an FBO. */ if (invert) { /* wpos_temp.y = wpos_input * wpostrans.xxxx + wpostrans.yyyy */ wpos_temp_y = nir_fadd(b, nir_fmul(b, nir_channel(b, wpos_temp, 1), nir_channel(b, wpostrans, 0)), nir_channel(b, wpostrans, 1)); } else { /* wpos_temp.y = wpos_input * wpostrans.zzzz + wpostrans.wwww */ wpos_temp_y = nir_fadd(b, nir_fmul(b, nir_channel(b, wpos_temp, 1), nir_channel(b, wpostrans, 2)), nir_channel(b, wpostrans, 3)); } wpos_temp = nir_vec4(b, nir_channel(b, wpos_temp, 0), wpos_temp_y, nir_channel(b, wpos_temp, 2), nir_channel(b, wpos_temp, 3)); nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_src_for_ssa(wpos_temp)); }
static nir_shader * build_nir_itob_compute_shader(struct radv_device *dev) { nir_builder b; const struct glsl_type *sampler_type = glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, GLSL_TYPE_FLOAT); const struct glsl_type *img_type = glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, GLSL_TYPE_FLOAT); nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_COMPUTE, NULL); b.shader->info->name = ralloc_strdup(b.shader, "meta_itob_cs"); b.shader->info->cs.local_size[0] = 16; b.shader->info->cs.local_size[1] = 16; b.shader->info->cs.local_size[2] = 1; nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex"); input_img->data.descriptor_set = 0; input_img->data.binding = 0; nir_variable *output_img = nir_variable_create(b.shader, nir_var_uniform, img_type, "out_img"); output_img->data.descriptor_set = 0; output_img->data.binding = 1; nir_ssa_def *invoc_id = nir_load_system_value(&b, nir_intrinsic_load_local_invocation_id, 0); nir_ssa_def *wg_id = nir_load_system_value(&b, nir_intrinsic_load_work_group_id, 0); nir_ssa_def *block_size = nir_imm_ivec4(&b, b.shader->info->cs.local_size[0], b.shader->info->cs.local_size[1], b.shader->info->cs.local_size[2], 0); nir_ssa_def *global_id = nir_iadd(&b, nir_imul(&b, wg_id, block_size), invoc_id); nir_intrinsic_instr *offset = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_push_constant); offset->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0)); offset->num_components = 2; nir_ssa_dest_init(&offset->instr, &offset->dest, 2, 32, "offset"); nir_builder_instr_insert(&b, &offset->instr); nir_intrinsic_instr *stride = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_push_constant); stride->src[0] = nir_src_for_ssa(nir_imm_int(&b, 8)); stride->num_components = 1; nir_ssa_dest_init(&stride->instr, &stride->dest, 1, 32, "stride"); nir_builder_instr_insert(&b, &stride->instr); nir_ssa_def *img_coord = nir_iadd(&b, global_id, &offset->dest.ssa); nir_tex_instr *tex = nir_tex_instr_create(b.shader, 2); tex->sampler_dim = GLSL_SAMPLER_DIM_2D; tex->op = nir_texop_txf; tex->src[0].src_type = nir_tex_src_coord; tex->src[0].src = nir_src_for_ssa(img_coord); tex->src[1].src_type = nir_tex_src_lod; tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0)); tex->dest_type = nir_type_float; tex->is_array = false; tex->coord_components = 2; tex->texture = nir_deref_var_create(tex, input_img); tex->sampler = NULL; nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex"); nir_builder_instr_insert(&b, &tex->instr); nir_ssa_def *pos_x = nir_channel(&b, global_id, 0); nir_ssa_def *pos_y = nir_channel(&b, global_id, 1); nir_ssa_def *tmp = nir_imul(&b, pos_y, &stride->dest.ssa); tmp = nir_iadd(&b, tmp, pos_x); nir_ssa_def *coord = nir_vec4(&b, tmp, tmp, tmp, tmp); nir_ssa_def *outval = &tex->dest.ssa; nir_intrinsic_instr *store = nir_intrinsic_instr_create(b.shader, nir_intrinsic_image_store); store->src[0] = nir_src_for_ssa(coord); store->src[1] = nir_src_for_ssa(nir_ssa_undef(&b, 1, 32)); store->src[2] = nir_src_for_ssa(outval); store->variables[0] = nir_deref_var_create(store, output_img); nir_builder_instr_insert(&b, &store->instr); return b.shader; }