nak: Add initial translation from NIR
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
committed by
Marge Bot
parent
a4a5fe2270
commit
5585f57c5c
@@ -3,10 +3,12 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
mod nak_from_nir;
|
||||
mod nak_ir;
|
||||
mod nir;
|
||||
|
||||
use nak_bindings::*;
|
||||
use nak_from_nir::*;
|
||||
|
||||
#[repr(C)]
|
||||
struct ShaderBin {
|
||||
@@ -23,9 +25,15 @@ pub extern "C" fn nak_shader_bin_destroy(bin: *mut nak_shader_bin) {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nak_compile_shader(
|
||||
_nir: *mut nir_shader,
|
||||
_nak: *const nak_compiler,
|
||||
nir: *mut nir_shader,
|
||||
nak: *const nak_compiler,
|
||||
) -> *mut nak_shader_bin {
|
||||
println!("Hello from rust!");
|
||||
unsafe { nak_postprocess_nir(nir, nak) };
|
||||
let nir = unsafe { &*nir };
|
||||
|
||||
let mut s = nak_shader_from_nir(nir);
|
||||
|
||||
println!("NAK IR:\n{}", &s);
|
||||
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright © 2022 Collabora, Ltd.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use crate::nak_ir::*;
|
||||
use crate::nir::*;
|
||||
|
||||
use nak_bindings::*;
|
||||
|
||||
struct ShaderFromNir<'a> {
|
||||
nir: &'a nir_shader,
|
||||
func: Option<Function>,
|
||||
instrs: Vec<Instr>,
|
||||
fs_out_regs: Vec<Src>,
|
||||
}
|
||||
|
||||
impl<'a> ShaderFromNir<'a> {
|
||||
fn new(nir: &'a nir_shader) -> Self {
|
||||
let mut fs_out_regs = Vec::new();
|
||||
if nir.info.stage() == MESA_SHADER_FRAGMENT {
|
||||
fs_out_regs
|
||||
.resize(nir.num_outputs.try_into().unwrap(), Src::new_zero());
|
||||
}
|
||||
|
||||
Self {
|
||||
nir: nir,
|
||||
func: None,
|
||||
instrs: Vec::new(),
|
||||
fs_out_regs: fs_out_regs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_ssa(&mut self, file: RegFile, comps: u8) -> Src {
|
||||
self.func.as_mut().unwrap().alloc_ssa(file, comps)
|
||||
}
|
||||
|
||||
fn ref_for_nir_def(&self, def: &nir_def) -> Src {
|
||||
assert!(def.bit_size == 32 || def.bit_size == 64);
|
||||
let dwords = (def.bit_size / 32) * def.num_components;
|
||||
//Src::new_ssa(def.index, dwords, !def.divergent)
|
||||
Src::new_ssa(RegFile::GPR, def.index, dwords)
|
||||
}
|
||||
|
||||
fn get_src(&self, src: &nir_src) -> Src {
|
||||
self.ref_for_nir_def(&src.as_def())
|
||||
}
|
||||
|
||||
fn get_dst(&self, def: &nir_def) -> Dst {
|
||||
self.ref_for_nir_def(def).as_dst()
|
||||
}
|
||||
|
||||
fn get_alu_src(&mut self, alu_src: &nir_alu_src) -> Src {
|
||||
assert!(alu_src.src.bit_size() == 32);
|
||||
if alu_src.src.num_components() == 1 {
|
||||
self.get_src(&alu_src.src)
|
||||
} else {
|
||||
let vec_src = self.get_src(&alu_src.src);
|
||||
let comp = self.alloc_ssa(vec_src.as_ssa().unwrap().file(), 1);
|
||||
let mut dsts = Vec::new();
|
||||
for c in 0..alu_src.src.num_components() {
|
||||
if c == alu_src.swizzle[0] {
|
||||
dsts.push(comp.as_dst());
|
||||
} else {
|
||||
dsts.push(Dst::Zero);
|
||||
}
|
||||
}
|
||||
self.instrs.push(Instr::new_split(&dsts, vec_src));
|
||||
comp
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_alu(&mut self, alu: &nir_alu_instr) {
|
||||
let mut srcs = Vec::new();
|
||||
for alu_src in alu.srcs_as_slice() {
|
||||
srcs.push(self.get_alu_src(alu_src));
|
||||
}
|
||||
let srcs = srcs;
|
||||
|
||||
let dst = self.get_dst(&alu.def);
|
||||
|
||||
match alu.op {
|
||||
nir_op_fadd => {
|
||||
self.instrs.push(Instr::new_fadd(dst, srcs[0], srcs[1]));
|
||||
}
|
||||
nir_op_mov => {
|
||||
self.instrs.push(Instr::new_mov(dst, srcs[0]));
|
||||
}
|
||||
nir_op_pack_64_2x32_split => {
|
||||
self.instrs.push(Instr::new_vec(dst, &[srcs[0], srcs[1]]));
|
||||
}
|
||||
_ => panic!("Unsupported ALU instruction"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_jump(&mut self, jump: &nir_jump_instr) {
|
||||
match jump.type_ {
|
||||
_ => panic!("Unsupported jump instruction"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_tex(&mut self, _tex: &nir_tex_instr) {
|
||||
panic!("Texture instructions unimplemented");
|
||||
}
|
||||
|
||||
fn parse_intrinsic(&mut self, intrin: &nir_intrinsic_instr) {
|
||||
let srcs = intrin.srcs_as_slice();
|
||||
match intrin.intrinsic {
|
||||
nir_intrinsic_load_input => {
|
||||
let addr = u16::try_from(intrin.base()).unwrap();
|
||||
let vtx = Src::new_zero();
|
||||
let offset = self.get_src(&srcs[0]);
|
||||
let dst = self.get_dst(&intrin.def);
|
||||
self.instrs.push(Instr::new_ald(dst, addr, vtx, offset));
|
||||
}
|
||||
nir_intrinsic_load_per_vertex_input => {
|
||||
let addr = u16::try_from(intrin.base()).unwrap();
|
||||
let vtx = self.get_src(&srcs[0]);
|
||||
let offset = self.get_src(&srcs[1]);
|
||||
let dst = self.get_dst(&intrin.def);
|
||||
self.instrs.push(Instr::new_ald(dst, addr, vtx, offset));
|
||||
}
|
||||
nir_intrinsic_store_output => {
|
||||
if self.nir.info.stage() == MESA_SHADER_FRAGMENT {
|
||||
/* We assume these only ever happen in the last block.
|
||||
* This is ensured by nir_lower_io_to_temporaries()
|
||||
*/
|
||||
let data = self.get_src(&srcs[0]);
|
||||
assert!(srcs[1].is_zero());
|
||||
let base: u8 = intrin.base().try_into().unwrap();
|
||||
let mut dsts = Vec::new();
|
||||
for c in 0..intrin.num_components {
|
||||
let tmp = self.alloc_ssa(RegFile::GPR, 1);
|
||||
self.fs_out_regs[(base + c) as usize] = tmp;
|
||||
dsts.push(tmp);
|
||||
}
|
||||
self.instrs.push(Instr::new_split(&dsts, data))
|
||||
} else {
|
||||
let data = self.get_src(&srcs[0]);
|
||||
let vtx = Src::new_zero();
|
||||
let offset = self.get_src(&srcs[1]);
|
||||
let addr: u16 = intrin.base().try_into().unwrap();
|
||||
self.instrs.push(Instr::new_ast(addr, data, vtx, offset))
|
||||
}
|
||||
}
|
||||
_ => panic!("Unsupported intrinsic instruction"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_load_const(&mut self, load_const: &nir_load_const_instr) {
|
||||
let dst = self.ref_for_nir_def(&load_const.def);
|
||||
let mut srcs = Vec::new();
|
||||
for c in 0..load_const.def.num_components {
|
||||
assert!(load_const.def.bit_size == 32);
|
||||
let imm_u32 = unsafe { load_const.values()[c as usize].u32_ };
|
||||
srcs.push(Src::new_imm_u32(imm_u32));
|
||||
}
|
||||
self.instrs.push(Instr::new_vec(dst, &srcs));
|
||||
}
|
||||
|
||||
fn parse_undef(&mut self, _ssa_undef: &nir_undef_instr) {
|
||||
panic!("SSA undef not implemented yet");
|
||||
}
|
||||
|
||||
fn parse_basic_block(&mut self, nb: &nir_block) -> BasicBlock {
|
||||
for ni in nb.iter_instr_list() {
|
||||
match ni.type_ {
|
||||
nir_instr_type_alu => self.parse_alu(ni.as_alu().unwrap()),
|
||||
nir_instr_type_jump => self.parse_jump(ni.as_jump().unwrap()),
|
||||
nir_instr_type_tex => self.parse_tex(ni.as_tex().unwrap()),
|
||||
nir_instr_type_intrinsic => {
|
||||
self.parse_intrinsic(ni.as_intrinsic().unwrap())
|
||||
}
|
||||
nir_instr_type_load_const => {
|
||||
self.parse_load_const(ni.as_load_const().unwrap())
|
||||
}
|
||||
nir_instr_type_undef => {
|
||||
self.parse_undef(ni.as_undef().unwrap())
|
||||
}
|
||||
_ => panic!("Unsupported instruction type"),
|
||||
}
|
||||
}
|
||||
let mut b = BasicBlock::new(0 /* TODO: Block indices */);
|
||||
b.instrs.append(&mut self.instrs);
|
||||
b
|
||||
}
|
||||
|
||||
pub fn parse_function_impl(&mut self, nfi: &nir_function_impl) -> Function {
|
||||
self.func = Some(Function::new(0, nfi.ssa_alloc));
|
||||
for node in nfi.iter_body() {
|
||||
/* TODO: Control-flow */
|
||||
let b = self.parse_basic_block(node.as_block().unwrap());
|
||||
self.func.as_mut().unwrap().blocks.push(b);
|
||||
}
|
||||
|
||||
let end_block = self.func.as_mut().unwrap().blocks.last_mut().unwrap();
|
||||
|
||||
if self.nir.info.stage() == MESA_SHADER_FRAGMENT
|
||||
&& nfi.function().is_entrypoint
|
||||
{
|
||||
let fs_out_regs =
|
||||
std::mem::replace(&mut self.fs_out_regs, Vec::new());
|
||||
end_block.instrs.push(Instr::new_fs_out(&fs_out_regs));
|
||||
}
|
||||
|
||||
end_block.instrs.push(Instr::new_exit());
|
||||
|
||||
self.func.take().unwrap()
|
||||
}
|
||||
|
||||
pub fn parse_shader(&mut self) -> Shader {
|
||||
let mut s = Shader::new();
|
||||
for nf in self.nir.iter_functions() {
|
||||
if let Some(nfi) = nf.get_impl() {
|
||||
let f = self.parse_function_impl(nfi);
|
||||
s.functions.push(f);
|
||||
}
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nak_shader_from_nir(ns: &nir_shader) -> Shader {
|
||||
ShaderFromNir::new(ns).parse_shader()
|
||||
}
|
||||
Reference in New Issue
Block a user