we store those arrays in local memory and reserve some space for each of the arrays. The arrays are stored in a packed format, because we know quite easily the context of each index. We don't do that in TGSI so far.
This causes various issues to come up in the MemoryOpt pass, because ld/st with indirects aren't guarenteed to be aligned to 0x10 anymore. v3: use fixed size vec4 arrays until we fix MemoryOpt Signed-off-by: Karol Herbst <kher...@redhat.com> --- .../drivers/nouveau/codegen/nv50_ir_from_nir.cpp | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp index ede6ee0119..82f388c2ac 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp @@ -73,6 +73,7 @@ public: typedef decltype(nir_ssa_def().index) NirSSADefIdx; typedef decltype(nir_ssa_def().bit_size) NirSSADefBitSize; typedef std::unordered_map<NirSSADefIdx, LValues> NirDefMap; + typedef std::unordered_map<NirSSADefIdx, uint32_t> NirArrayLMemOffsets; typedef std::unordered_map<decltype(nir_block().index), BasicBlock*> NirBlockMap; Converter(Program *, nir_shader *, nv50_ir_prog_info *); @@ -139,6 +140,7 @@ private: NirDefMap ssaDefs; NirDefMap regDefs; + NirArrayLMemOffsets regToLmemOffset; NirBlockMap blocks; unsigned int curLoopDepth; @@ -1096,6 +1098,7 @@ bool Converter::assignSlots() { bool Converter::parseNIR() { + info->bin.tlsSpace = 0; info->io.clipDistances = nir->info.clip_distance_array_size; info->io.cullDistances = nir->info.cull_distance_array_size; @@ -1183,6 +1186,17 @@ Converter::visit(nir_function *function) break; } + nir_foreach_register(reg, &function->impl->registers) { + if (reg->num_array_elems) { + // TODO: packed variables would be nice, but MemoryOpt fails + // uint32_t size = reg->num_components * reg->num_array_elems * (reg->bit_size / 8); + uint32_t size = 4 * reg->num_array_elems * (reg->bit_size / 8); + // reserve some lmem + regToLmemOffset[reg->index] = info->bin.tlsSpace; + info->bin.tlsSpace += size; + } + } + nir_index_ssa_defs(function->impl); foreach_list_typed(nir_cf_node, node, node, &function->impl->body) { if (!visit(node)) @@ -1778,6 +1792,51 @@ Converter::visit(nir_alu_instr *insn) * 2. they basically just merge multiple values into one data type */ CASE_OPFI(mov): + if (!insn->dest.dest.is_ssa && insn->dest.dest.reg.reg->num_array_elems) { + nir_reg_dest& reg = insn->dest.dest.reg; + auto goffset = regToLmemOffset[reg.reg->index]; + auto comps = reg.reg->num_components; + auto size = reg.reg->bit_size / 8; + auto csize = 0x10; // TODO after fixing MemoryOpts: comps * size; + auto aoffset = csize * reg.base_offset; + Value *indirect = nullptr; + + if (reg.indirect) + indirect = mkOp2v(OP_MUL, TYPE_U32, getSSA(4, FILE_ADDRESS), getSrc(reg.indirect, 0), mkImm(csize)); + + for (auto i = 0u; i < comps; ++i) { + if (!((1u << i) & insn->dest.write_mask)) + continue; + + Symbol *sym = mkSymbol(FILE_MEMORY_LOCAL, 0, dType, goffset + aoffset + i * size); + mkStore(OP_STORE, dType, sym, indirect, getSrc(&insn->src[0], i)); + } + break; + } else if (!insn->src[0].src.is_ssa && insn->src[0].src.reg.reg->num_array_elems) { + LValues &newDefs = convert(&insn->dest); + nir_reg_src& reg = insn->src[0].src.reg; + auto goffset = regToLmemOffset[reg.reg->index]; + // auto comps = reg.reg->num_components; + auto size = reg.reg->bit_size / 8; + auto csize = 0x10; // TODO after fixing MemoryOpts: comps * size; + auto aoffset = csize * reg.base_offset; + Value *indirect = nullptr; + + if (reg.indirect) + indirect = mkOp2v(OP_MUL, TYPE_U32, getSSA(4, FILE_ADDRESS), getSrc(reg.indirect, 0), mkImm(csize)); + + for (auto i = 0u; i < newDefs.size(); ++i) { + Symbol *sym = mkSymbol(FILE_MEMORY_LOCAL, 0, dType, goffset + aoffset + i * size); + mkLoad(dType, newDefs[i], sym, indirect); + } + break; + } else { + LValues &newDefs = convert(&insn->dest); + for (LValues::size_type c = 0u; c < newDefs.size(); ++c) { + mkMov(newDefs[c], getSrc(&insn->src[0], c), dType); + } + } + break; case nir_op_vec2: case nir_op_vec3: case nir_op_vec4: { @@ -2178,6 +2237,7 @@ Converter::run() NIR_PASS(progress, nir, nir_opt_dead_cf); } while (progress); + NIR_PASS_V(nir, nir_lower_locals_to_regs); NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_local); NIR_PASS_V(nir, nir_convert_from_ssa, true); -- 2.14.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev