diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/a2xx/fd2_program.c')
-rw-r--r-- | src/gallium/drivers/freedreno/a2xx/fd2_program.c | 521 |
1 files changed, 215 insertions, 306 deletions
diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_program.c b/src/gallium/drivers/freedreno/a2xx/fd2_program.c index 56b3ab2aaeb..da020443bd9 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_program.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_program.c @@ -22,6 +22,7 @@ * * Authors: * Rob Clark <robclark@freedesktop.org> + * Jonathan Marek <jonathan@marek.ca> */ #include "pipe/p_state.h" @@ -34,18 +35,20 @@ #include "freedreno_program.h" +#include "ir2.h" #include "fd2_program.h" -#include "fd2_compiler.h" #include "fd2_texture.h" #include "fd2_util.h" +#include "instr-a2xx.h" static struct fd2_shader_stateobj * -create_shader(gl_shader_stage type) +create_shader(struct pipe_context *pctx, gl_shader_stage type) { struct fd2_shader_stateobj *so = CALLOC_STRUCT(fd2_shader_stateobj); if (!so) return NULL; so->type = type; + so->is_a20x = is_a20x(fd_context(pctx)->screen); return so; } @@ -54,89 +57,67 @@ delete_shader(struct fd2_shader_stateobj *so) { if (!so) return; - ir2_shader_destroy(so->ir); - free(so->tokens); - free(so->bin); + ralloc_free(so->nir); + for (int i = 0; i < ARRAY_SIZE(so->variant); i++) + free(so->variant[i].info.dwords); free(so); } -static struct fd2_shader_stateobj * -assemble(struct fd2_shader_stateobj *so) +static void +emit(struct fd_ringbuffer *ring, gl_shader_stage type, + struct ir2_shader_info *info) { - free(so->bin); - so->bin = ir2_shader_assemble(so->ir, &so->info); - if (!so->bin) - goto fail; + unsigned i; - if (fd_mesa_debug & FD_DBG_DISASM) { - DBG("disassemble: type=%d", so->type); - disasm_a2xx(so->bin, so->info.sizedwords, 0, so->type); - } + assert(info->sizedwords); - return so; + OUT_PKT3(ring, CP_IM_LOAD_IMMEDIATE, 2 + info->sizedwords); + OUT_RING(ring, type == MESA_SHADER_FRAGMENT); + OUT_RING(ring, info->sizedwords); + for (i = 0; i < info->sizedwords; i++) + OUT_RING(ring, info->dwords[i]); +} -fail: - debug_error("assemble failed!"); - delete_shader(so); - return NULL; +static int +ir2_glsl_type_size(const struct glsl_type *type) +{ + return glsl_count_attribute_slots(type, false); } -static struct fd2_shader_stateobj * -compile(struct fd_program_stateobj *prog, struct fd2_shader_stateobj *so) +static void * +fd2_fp_state_create(struct pipe_context *pctx, + const struct pipe_shader_state *cso) { - int ret; + struct fd2_shader_stateobj *so = create_shader(pctx, MESA_SHADER_FRAGMENT); + if (!so) + return NULL; - if (fd_mesa_debug & FD_DBG_DISASM) { - DBG("dump tgsi: type=%d", so->type); - tgsi_dump(so->tokens, 0); + if (cso->type == PIPE_SHADER_IR_NIR) { + so->nir = cso->ir.nir; + NIR_PASS_V(so->nir, nir_lower_io, nir_var_all, ir2_glsl_type_size, + (nir_lower_io_options)0); + } else { + assert(cso->type == PIPE_SHADER_IR_TGSI); + so->nir = ir2_tgsi_to_nir(cso->tokens); } - ret = fd2_compile_shader(prog, so); - if (ret) + if (ir2_optimize_nir(so->nir, true)) goto fail; - /* NOTE: we don't assemble yet because for VS we don't know the - * type information for vertex fetch yet.. so those need to be - * patched up later before assembling. - */ + so->first_immediate = so->nir->num_uniforms; - so->info.sizedwords = 0; + ir2_compile(so, 0, NULL); + ralloc_free(so->nir); + so->nir = NULL; return so; fail: - debug_error("compile failed!"); delete_shader(so); return NULL; } static void -emit(struct fd_ringbuffer *ring, struct fd2_shader_stateobj *so) -{ - unsigned i; - - if (so->info.sizedwords == 0) - assemble(so); - - OUT_PKT3(ring, CP_IM_LOAD_IMMEDIATE, 2 + so->info.sizedwords); - OUT_RING(ring, (so->type == MESA_SHADER_VERTEX) ? 0 : 1); - OUT_RING(ring, so->info.sizedwords); - for (i = 0; i < so->info.sizedwords; i++) - OUT_RING(ring, so->bin[i]); -} - -static void * -fd2_fp_state_create(struct pipe_context *pctx, - const struct pipe_shader_state *cso) -{ - struct fd2_shader_stateobj *so = create_shader(MESA_SHADER_FRAGMENT); - if (!so) - return NULL; - so->tokens = tgsi_dup_tokens(cso->tokens); - return so; -} - -static void fd2_fp_state_delete(struct pipe_context *pctx, void *hwcso) { struct fd2_shader_stateobj *so = hwcso; @@ -147,11 +128,32 @@ static void * fd2_vp_state_create(struct pipe_context *pctx, const struct pipe_shader_state *cso) { - struct fd2_shader_stateobj *so = create_shader(MESA_SHADER_VERTEX); + struct fd2_shader_stateobj *so = create_shader(pctx, MESA_SHADER_VERTEX); if (!so) return NULL; - so->tokens = tgsi_dup_tokens(cso->tokens); + + if (cso->type == PIPE_SHADER_IR_NIR) { + so->nir = cso->ir.nir; + NIR_PASS_V(so->nir, nir_lower_io, nir_var_all, ir2_glsl_type_size, + (nir_lower_io_options)0); + } else { + assert(cso->type == PIPE_SHADER_IR_TGSI); + so->nir = ir2_tgsi_to_nir(cso->tokens); + } + + if (ir2_optimize_nir(so->nir, true)) + goto fail; + + so->first_immediate = so->nir->num_uniforms; + + /* compile binning variant now */ + ir2_compile(so, 0, NULL); + return so; + +fail: + delete_shader(so); + return NULL; } static void @@ -162,277 +164,145 @@ fd2_vp_state_delete(struct pipe_context *pctx, void *hwcso) } static void -patch_vtx_fetches(struct fd_context *ctx, struct fd2_shader_stateobj *so, - struct fd_vertex_stateobj *vtx) +patch_vtx_fetch(struct fd_context *ctx, struct pipe_vertex_element *elem, + instr_fetch_vtx_t *instr, uint16_t dst_swiz) { - unsigned i; - - assert(so->num_vfetch_instrs == vtx->num_elements); - - /* update vtx fetch instructions: */ - for (i = 0; i < so->num_vfetch_instrs; i++) { - struct ir2_instruction *instr = so->vfetch_instrs[i]; - struct pipe_vertex_element *elem = &vtx->pipe[i]; - struct pipe_vertex_buffer *vb = + struct pipe_vertex_buffer *vb = &ctx->vtx.vertexbuf.vb[elem->vertex_buffer_index]; - enum pipe_format format = elem->src_format; - const struct util_format_description *desc = - util_format_description(format); - unsigned j; - - /* Find the first non-VOID channel. */ - for (j = 0; j < 4; j++) - if (desc->channel[j].type != UTIL_FORMAT_TYPE_VOID) - break; - - /* CI/CIS can probably be set in compiler instead: */ - instr->fetch.const_idx = 20 + (i / 3); - instr->fetch.const_idx_sel = i % 3; - - instr->fetch.fmt = fd2_pipe2surface(format); - instr->fetch.is_normalized = desc->channel[j].normalized; - instr->fetch.is_signed = - desc->channel[j].type == UTIL_FORMAT_TYPE_SIGNED; - instr->fetch.stride = vb->stride ? : 1; - instr->fetch.offset = elem->src_offset; - - for (j = 0; j < 4; j++) - instr->dst_reg.swizzle[j] = "xyzw01__"[desc->swizzle[j]]; - - assert(instr->fetch.fmt != ~0); - - DBG("vtx[%d]: %s (%d), ci=%d, cis=%d, id=%d, swizzle=%s, " - "stride=%d, offset=%d", - i, util_format_name(format), - instr->fetch.fmt, - instr->fetch.const_idx, - instr->fetch.const_idx_sel, - elem->instance_divisor, - instr->dst_reg.swizzle, - instr->fetch.stride, - instr->fetch.offset); + enum pipe_format format = elem->src_format; + const struct util_format_description *desc = + util_format_description(format); + unsigned j; + + /* Find the first non-VOID channel. */ + for (j = 0; j < 4; j++) + if (desc->channel[j].type != UTIL_FORMAT_TYPE_VOID) + break; + + instr->format = fd2_pipe2surface(format); + instr->num_format_all = !desc->channel[j].normalized; + instr->format_comp_all = desc->channel[j].type == UTIL_FORMAT_TYPE_SIGNED; + instr->stride = vb->stride; + instr->offset = elem->src_offset; + + unsigned swiz = 0; + for (int i = 0; i < 4; i++) { + unsigned s = dst_swiz >> i*3 & 7; + swiz |= (s >= 4 ? s : desc->swizzle[s]) << i*3; } - - /* trigger re-assemble: */ - so->info.sizedwords = 0; + instr->dst_swiz = swiz; } static void -patch_tex_fetches(struct fd_context *ctx, struct fd2_shader_stateobj *so, - struct fd_texture_stateobj *tex) +patch_fetches(struct fd_context *ctx, struct ir2_shader_info *info, + struct fd_vertex_stateobj *vtx, struct fd_texture_stateobj *tex) { - unsigned i; - - /* update tex fetch instructions: */ - for (i = 0; i < so->num_tfetch_instrs; i++) { - struct ir2_instruction *instr = so->tfetch_instrs[i].instr; - unsigned samp_id = so->tfetch_instrs[i].samp_id; - unsigned const_idx = fd2_get_const_idx(ctx, tex, samp_id); + for (int i = 0; i < info->num_fetch_instrs; i++) { + struct ir2_fetch_info *fi = &info->fetch_info[i]; + + instr_fetch_t *instr = (instr_fetch_t*) &info->dwords[fi->offset]; + if (instr->opc == VTX_FETCH) { + unsigned idx = (instr->vtx.const_index - 20) * 3 + + instr->vtx.const_index_sel; + patch_vtx_fetch(ctx, &vtx->pipe[idx], &instr->vtx, fi->vtx.dst_swiz); + continue; + } - if (const_idx != instr->fetch.const_idx) { - instr->fetch.const_idx = const_idx; - /* trigger re-assemble: */ - so->info.sizedwords = 0; + assert(instr->opc == TEX_FETCH); + instr->tex.const_idx = fd2_get_const_idx(ctx, tex, fi->tex.samp_id); + instr->tex.src_swiz = fi->tex.src_swiz; + if (fd2_texture_swap_xy(tex, fi->tex.samp_id)) { + unsigned x = instr->tex.src_swiz; + instr->tex.src_swiz = (x & 0x30) | (x & 3) << 2 | (x >> 2 & 3); } } } void -fd2_program_validate(struct fd_context *ctx) +fd2_program_emit(struct fd_context *ctx, struct fd_ringbuffer *ring, + struct fd_program_stateobj *prog) { - struct fd_program_stateobj *prog = &ctx->prog; - bool dirty_fp = !!(ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_PROG); - bool dirty_vp = !!(ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_PROG); - - /* if vertex or frag shader is dirty, we may need to recompile. Compile - * frag shader first, as that assigns the register slots for exports - * from the vertex shader. And therefore if frag shader has changed we - * need to recompile both vert and frag shader. - */ - if (dirty_fp) - compile(prog, prog->fp); - - if (dirty_fp || dirty_vp) - compile(prog, prog->vp); - - /* if necessary, fix up vertex fetch instructions: */ - if (ctx->dirty & (FD_DIRTY_VTXSTATE | FD_DIRTY_PROG)) - patch_vtx_fetches(ctx, prog->vp, ctx->vtx.vtx); - - /* if necessary, fix up texture fetch instructions: */ - if (ctx->dirty & (FD_DIRTY_TEXSTATE | FD_DIRTY_PROG)) { - patch_tex_fetches(ctx, prog->vp, &ctx->tex[PIPE_SHADER_VERTEX]); - patch_tex_fetches(ctx, prog->fp, &ctx->tex[PIPE_SHADER_FRAGMENT]); + struct fd2_shader_stateobj *fp = NULL, *vp; + struct ir2_shader_info *fpi, *vpi; + struct ir2_frag_linkage *f; + uint8_t vs_gprs, fs_gprs = 0, vs_export = 0; + enum a2xx_sq_ps_vtx_mode mode = POSITION_1_VECTOR; + bool binning = (ctx->batch && ring == ctx->batch->binning); + unsigned variant = 0; + + vp = prog->vp; + + /* find variant matching the linked fragment shader */ + if (!binning) { + fp = prog->fp; + for (variant = 1; variant < ARRAY_SIZE(vp->variant); variant++) { + /* if checked all variants, compile a new variant */ + if (!vp->variant[variant].info.sizedwords) { + ir2_compile(vp, variant, fp); + break; + } + + /* check if fragment shader linkage matches */ + if (!memcmp(&vp->variant[variant].f, &fp->variant[0].f, + sizeof(struct ir2_frag_linkage))) + break; + } + assert(variant < ARRAY_SIZE(vp->variant)); } -} -void -fd2_program_emit(struct fd_ringbuffer *ring, - struct fd_program_stateobj *prog) -{ - struct ir2_shader_info *vsi = - &((struct fd2_shader_stateobj *)prog->vp)->info; - struct ir2_shader_info *fsi = - &((struct fd2_shader_stateobj *)prog->fp)->info; - uint8_t vs_gprs, fs_gprs, vs_export; + vpi = &vp->variant[variant].info; + fpi = &fp->variant[0].info; + f = &fp->variant[0].f; + + /* clear/gmem2mem/mem2gmem need to be changed to remove this condition */ + if (prog != &ctx->solid_prog && prog != &ctx->blit_prog[0]) { + patch_fetches(ctx, vpi, ctx->vtx.vtx, &ctx->tex[PIPE_SHADER_VERTEX]); + if (fp) + patch_fetches(ctx, fpi, NULL, &ctx->tex[PIPE_SHADER_FRAGMENT]); + } - emit(ring, prog->vp); - emit(ring, prog->fp); + emit(ring, MESA_SHADER_VERTEX, vpi); - vs_gprs = (vsi->max_reg < 0) ? 0x80 : vsi->max_reg; - fs_gprs = (fsi->max_reg < 0) ? 0x80 : fsi->max_reg; - vs_export = MAX2(1, prog->num_exports) - 1; + if (fp) { + emit(ring, MESA_SHADER_FRAGMENT, fpi); + fs_gprs = (fpi->max_reg < 0) ? 0x80 : fpi->max_reg; + vs_export = MAX2(1, f->inputs_count) - 1; + } + + vs_gprs = (vpi->max_reg < 0) ? 0x80 : vpi->max_reg; + + if (vp->writes_psize && !binning) + mode = POSITION_2_VECTORS_SPRITE; + + /* set register to use for param (fragcoord/pointcoord/frontfacing) */ + OUT_PKT3(ring, CP_SET_CONSTANT, 2); + OUT_RING(ring, CP_REG(REG_A2XX_SQ_CONTEXT_MISC)); + OUT_RING(ring, A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL(CENTERS_ONLY) | + COND(fp, A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS(f->inputs_count)) | + /* we need SCREEN_XY for both fragcoord and frontfacing */ + A2XX_SQ_CONTEXT_MISC_SC_OUTPUT_SCREEN_XY); OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_SQ_PROGRAM_CNTL)); - OUT_RING(ring, A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE(POSITION_2_VECTORS_SPRITE) | + OUT_RING(ring, A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE(2) | + A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE(mode) | A2XX_SQ_PROGRAM_CNTL_VS_RESOURCE | A2XX_SQ_PROGRAM_CNTL_PS_RESOURCE | A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT(vs_export) | A2XX_SQ_PROGRAM_CNTL_PS_REGS(fs_gprs) | - A2XX_SQ_PROGRAM_CNTL_VS_REGS(vs_gprs)); -} - -/* Creates shader: - * EXEC ADDR(0x2) CNT(0x1) - * (S)FETCH: SAMPLE R0.xyzw = R0.xyx CONST(0) LOCATION(CENTER) - * ALLOC PARAM/PIXEL SIZE(0x0) - * EXEC_END ADDR(0x3) CNT(0x1) - * ALU: MAXv export0 = R0, R0 ; gl_FragColor - * NOP - */ -static struct fd2_shader_stateobj * -create_blit_fp(void) -{ - struct fd2_shader_stateobj *so = create_shader(MESA_SHADER_FRAGMENT); - struct ir2_instruction *instr; - - if (!so) - return NULL; - - so->ir = ir2_shader_create(); - - instr = ir2_instr_create_tex_fetch(so->ir, 0); - ir2_dst_create(instr, 0, "xyzw", 0); - ir2_reg_create(instr, 0, "xyx", IR2_REG_INPUT); - instr->sync = true; - - instr = ir2_instr_create_alu_v(so->ir, MAXv); - ir2_dst_create(instr, 0, NULL, IR2_REG_EXPORT); - ir2_reg_create(instr, 0, NULL, 0); - ir2_reg_create(instr, 0, NULL, 0); - - return assemble(so); -} - -/* Creates shader: -* EXEC ADDR(0x3) CNT(0x2) -* FETCH: VERTEX R1.xy01 = R0.x FMT_32_32_FLOAT UNSIGNED STRIDE(8) CONST(26, 1) -* FETCH: VERTEX R2.xyz1 = R0.x FMT_32_32_32_FLOAT UNSIGNED STRIDE(12) CONST(26, 0) -* ALLOC POSITION SIZE(0x0) -* EXEC ADDR(0x5) CNT(0x1) -* ALU: MAXv export62 = R2, R2 ; gl_Position -* ALLOC PARAM/PIXEL SIZE(0x0) -* EXEC_END ADDR(0x6) CNT(0x1) -* ALU: MAXv export0 = R1, R1 -* NOP - */ -static struct fd2_shader_stateobj * -create_blit_vp(void) -{ - struct fd2_shader_stateobj *so = create_shader(MESA_SHADER_VERTEX); - struct ir2_instruction *instr; - - if (!so) - return NULL; - - so->ir = ir2_shader_create(); - - instr = ir2_instr_create_vtx_fetch(so->ir, 26, 1, FMT_32_32_FLOAT, false, 8); - instr->fetch.is_normalized = true; - ir2_dst_create(instr, 1, "xy01", 0); - ir2_reg_create(instr, 0, "x", IR2_REG_INPUT); - - instr = ir2_instr_create_vtx_fetch(so->ir, 26, 0, FMT_32_32_32_FLOAT, false, 12); - instr->fetch.is_normalized = true; - ir2_dst_create(instr, 2, "xyz1", 0); - ir2_reg_create(instr, 0, "x", IR2_REG_INPUT); - - instr = ir2_instr_create_alu_v(so->ir, MAXv); - ir2_dst_create(instr, 62, NULL, IR2_REG_EXPORT); - ir2_reg_create(instr, 2, NULL, 0); - ir2_reg_create(instr, 2, NULL, 0); - - instr = ir2_instr_create_alu_v(so->ir, MAXv); - ir2_dst_create(instr, 0, NULL, IR2_REG_EXPORT); - ir2_reg_create(instr, 1, NULL, 0); - ir2_reg_create(instr, 1, NULL, 0); - - return assemble(so); -} - -/* Creates shader: - * ALLOC PARAM/PIXEL SIZE(0x0) - * EXEC_END ADDR(0x1) CNT(0x1) - * ALU: MAXv export0 = C0, C0 ; gl_FragColor - */ -static struct fd2_shader_stateobj * -create_solid_fp(void) -{ - struct fd2_shader_stateobj *so = create_shader(MESA_SHADER_FRAGMENT); - struct ir2_instruction *instr; - - if (!so) - return NULL; - - so->ir = ir2_shader_create(); - - instr = ir2_instr_create_alu_v(so->ir, MAXv); - ir2_dst_create(instr, 0, NULL, IR2_REG_EXPORT); - ir2_reg_create(instr, 0, NULL, IR2_REG_CONST); - ir2_reg_create(instr, 0, NULL, IR2_REG_CONST); - - return assemble(so); -} - -/* Creates shader: - * EXEC ADDR(0x3) CNT(0x1) - * (S)FETCH: VERTEX R1.xyz1 = R0.x FMT_32_32_32_FLOAT - * UNSIGNED STRIDE(12) CONST(26, 0) - * ALLOC POSITION SIZE(0x0) - * EXEC ADDR(0x4) CNT(0x1) - * ALU: MAXv export62 = R1, R1 ; gl_Position - * ALLOC PARAM/PIXEL SIZE(0x0) - * EXEC_END ADDR(0x5) CNT(0x0) - */ -static struct fd2_shader_stateobj * -create_solid_vp(void) -{ - struct fd2_shader_stateobj *so = create_shader(MESA_SHADER_VERTEX); - struct ir2_instruction *instr; - - if (!so) - return NULL; - - so->ir = ir2_shader_create(); - - instr = ir2_instr_create_vtx_fetch(so->ir, 26, 0, FMT_32_32_32_FLOAT, false, 12); - ir2_dst_create(instr, 1, "xyz1", 0); - ir2_reg_create(instr, 0, "x", IR2_REG_INPUT); - - instr = ir2_instr_create_alu_v(so->ir, MAXv); - ir2_dst_create(instr, 62, NULL, IR2_REG_EXPORT); - ir2_reg_create(instr, 1, NULL, 0); - ir2_reg_create(instr, 1, NULL, 0); - - - return assemble(so); + A2XX_SQ_PROGRAM_CNTL_VS_REGS(vs_gprs) | + COND(fp && fp->need_param, A2XX_SQ_PROGRAM_CNTL_PARAM_GEN) | + COND(!fp, A2XX_SQ_PROGRAM_CNTL_GEN_INDEX_VTX)); } void fd2_prog_init(struct pipe_context *pctx) { struct fd_context *ctx = fd_context(pctx); + struct fd_program_stateobj *prog; + struct fd2_shader_stateobj *so; + struct ir2_shader_info *info; + instr_fetch_vtx_t *instr; pctx->create_fs_state = fd2_fp_state_create; pctx->delete_fs_state = fd2_fp_state_delete; @@ -442,8 +312,47 @@ fd2_prog_init(struct pipe_context *pctx) fd_prog_init(pctx); - ctx->solid_prog.fp = create_solid_fp(); - ctx->solid_prog.vp = create_solid_vp(); - ctx->blit_prog[0].fp = create_blit_fp(); - ctx->blit_prog[0].vp = create_blit_vp(); + /* XXX maybe its possible to reuse patch_vtx_fetch somehow? */ + + prog = &ctx->solid_prog; + so = prog->vp; + ir2_compile(prog->vp, 1, prog->fp); + +#define IR2_FETCH_SWIZ_XY01 0xb08 +#define IR2_FETCH_SWIZ_XYZ1 0xa88 + + info = &so->variant[1].info; + + instr = (instr_fetch_vtx_t*) &info->dwords[info->fetch_info[0].offset]; + instr->const_index = 26; + instr->const_index_sel = 0; + instr->format = FMT_32_32_32_FLOAT; + instr->format_comp_all = false; + instr->stride = 12; + instr->num_format_all = true; + instr->dst_swiz = IR2_FETCH_SWIZ_XYZ1; + + prog = &ctx->blit_prog[0]; + so = prog->vp; + ir2_compile(prog->vp, 1, prog->fp); + + info = &so->variant[1].info; + + instr = (instr_fetch_vtx_t*) &info->dwords[info->fetch_info[0].offset]; + instr->const_index = 26; + instr->const_index_sel = 1; + instr->format = FMT_32_32_FLOAT; + instr->format_comp_all = false; + instr->stride = 8; + instr->num_format_all = false; + instr->dst_swiz = IR2_FETCH_SWIZ_XY01; + + instr = (instr_fetch_vtx_t*) &info->dwords[info->fetch_info[1].offset]; + instr->const_index = 26; + instr->const_index_sel = 0; + instr->format = FMT_32_32_32_FLOAT; + instr->format_comp_all = false; + instr->stride = 12; + instr->num_format_all = false; + instr->dst_swiz = IR2_FETCH_SWIZ_XYZ1; } |