1*61046927SAndroid Build Coastguard Worker // Copyright © 2022 Collabora, Ltd.
2*61046927SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker
4*61046927SAndroid Build Coastguard Worker use crate::from_nir::*;
5*61046927SAndroid Build Coastguard Worker use crate::ir::{ShaderInfo, ShaderIoInfo, ShaderModel, ShaderStageInfo};
6*61046927SAndroid Build Coastguard Worker use crate::sm50::ShaderModel50;
7*61046927SAndroid Build Coastguard Worker use crate::sm70::ShaderModel70;
8*61046927SAndroid Build Coastguard Worker use crate::sph;
9*61046927SAndroid Build Coastguard Worker
10*61046927SAndroid Build Coastguard Worker use compiler::bindings::*;
11*61046927SAndroid Build Coastguard Worker use nak_bindings::*;
12*61046927SAndroid Build Coastguard Worker
13*61046927SAndroid Build Coastguard Worker use std::cmp::max;
14*61046927SAndroid Build Coastguard Worker use std::env;
15*61046927SAndroid Build Coastguard Worker use std::ffi::{CStr, CString};
16*61046927SAndroid Build Coastguard Worker use std::fmt::Write;
17*61046927SAndroid Build Coastguard Worker use std::os::raw::c_void;
18*61046927SAndroid Build Coastguard Worker use std::sync::OnceLock;
19*61046927SAndroid Build Coastguard Worker
20*61046927SAndroid Build Coastguard Worker #[repr(u8)]
21*61046927SAndroid Build Coastguard Worker enum DebugFlags {
22*61046927SAndroid Build Coastguard Worker Print,
23*61046927SAndroid Build Coastguard Worker Serial,
24*61046927SAndroid Build Coastguard Worker Spill,
25*61046927SAndroid Build Coastguard Worker Annotate,
26*61046927SAndroid Build Coastguard Worker NoUgpr,
27*61046927SAndroid Build Coastguard Worker }
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker pub struct Debug {
30*61046927SAndroid Build Coastguard Worker flags: u32,
31*61046927SAndroid Build Coastguard Worker }
32*61046927SAndroid Build Coastguard Worker
33*61046927SAndroid Build Coastguard Worker impl Debug {
new() -> Debug34*61046927SAndroid Build Coastguard Worker fn new() -> Debug {
35*61046927SAndroid Build Coastguard Worker let debug_var = "NAK_DEBUG";
36*61046927SAndroid Build Coastguard Worker let debug_str = match env::var(debug_var) {
37*61046927SAndroid Build Coastguard Worker Ok(s) => s,
38*61046927SAndroid Build Coastguard Worker Err(_) => {
39*61046927SAndroid Build Coastguard Worker return Debug { flags: 0 };
40*61046927SAndroid Build Coastguard Worker }
41*61046927SAndroid Build Coastguard Worker };
42*61046927SAndroid Build Coastguard Worker
43*61046927SAndroid Build Coastguard Worker let mut flags = 0;
44*61046927SAndroid Build Coastguard Worker for flag in debug_str.split(',') {
45*61046927SAndroid Build Coastguard Worker match flag.trim() {
46*61046927SAndroid Build Coastguard Worker "print" => flags |= 1 << DebugFlags::Print as u8,
47*61046927SAndroid Build Coastguard Worker "serial" => flags |= 1 << DebugFlags::Serial as u8,
48*61046927SAndroid Build Coastguard Worker "spill" => flags |= 1 << DebugFlags::Spill as u8,
49*61046927SAndroid Build Coastguard Worker "annotate" => flags |= 1 << DebugFlags::Annotate as u8,
50*61046927SAndroid Build Coastguard Worker "nougpr" => flags |= 1 << DebugFlags::NoUgpr as u8,
51*61046927SAndroid Build Coastguard Worker unk => eprintln!("Unknown NAK_DEBUG flag \"{}\"", unk),
52*61046927SAndroid Build Coastguard Worker }
53*61046927SAndroid Build Coastguard Worker }
54*61046927SAndroid Build Coastguard Worker Debug { flags: flags }
55*61046927SAndroid Build Coastguard Worker }
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Worker pub trait GetDebugFlags {
debug_flags(&self) -> u3259*61046927SAndroid Build Coastguard Worker fn debug_flags(&self) -> u32;
60*61046927SAndroid Build Coastguard Worker
print(&self) -> bool61*61046927SAndroid Build Coastguard Worker fn print(&self) -> bool {
62*61046927SAndroid Build Coastguard Worker self.debug_flags() & (1 << DebugFlags::Print as u8) != 0
63*61046927SAndroid Build Coastguard Worker }
64*61046927SAndroid Build Coastguard Worker
serial(&self) -> bool65*61046927SAndroid Build Coastguard Worker fn serial(&self) -> bool {
66*61046927SAndroid Build Coastguard Worker self.debug_flags() & (1 << DebugFlags::Serial as u8) != 0
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker
spill(&self) -> bool69*61046927SAndroid Build Coastguard Worker fn spill(&self) -> bool {
70*61046927SAndroid Build Coastguard Worker self.debug_flags() & (1 << DebugFlags::Spill as u8) != 0
71*61046927SAndroid Build Coastguard Worker }
72*61046927SAndroid Build Coastguard Worker
annotate(&self) -> bool73*61046927SAndroid Build Coastguard Worker fn annotate(&self) -> bool {
74*61046927SAndroid Build Coastguard Worker self.debug_flags() & (1 << DebugFlags::Annotate as u8) != 0
75*61046927SAndroid Build Coastguard Worker }
76*61046927SAndroid Build Coastguard Worker
no_ugpr(&self) -> bool77*61046927SAndroid Build Coastguard Worker fn no_ugpr(&self) -> bool {
78*61046927SAndroid Build Coastguard Worker self.debug_flags() & (1 << DebugFlags::NoUgpr as u8) != 0
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker
82*61046927SAndroid Build Coastguard Worker pub static DEBUG: OnceLock<Debug> = OnceLock::new();
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker impl GetDebugFlags for OnceLock<Debug> {
debug_flags(&self) -> u3285*61046927SAndroid Build Coastguard Worker fn debug_flags(&self) -> u32 {
86*61046927SAndroid Build Coastguard Worker self.get_or_init(Debug::new).flags
87*61046927SAndroid Build Coastguard Worker }
88*61046927SAndroid Build Coastguard Worker }
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_should_print_nir() -> bool91*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_should_print_nir() -> bool {
92*61046927SAndroid Build Coastguard Worker DEBUG.print()
93*61046927SAndroid Build Coastguard Worker }
94*61046927SAndroid Build Coastguard Worker
nir_options(dev: &nv_device_info) -> nir_shader_compiler_options95*61046927SAndroid Build Coastguard Worker fn nir_options(dev: &nv_device_info) -> nir_shader_compiler_options {
96*61046927SAndroid Build Coastguard Worker let mut op: nir_shader_compiler_options = unsafe { std::mem::zeroed() };
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker op.lower_fdiv = true;
99*61046927SAndroid Build Coastguard Worker op.fuse_ffma16 = true;
100*61046927SAndroid Build Coastguard Worker op.fuse_ffma32 = true;
101*61046927SAndroid Build Coastguard Worker op.fuse_ffma64 = true;
102*61046927SAndroid Build Coastguard Worker op.lower_flrp16 = true;
103*61046927SAndroid Build Coastguard Worker op.lower_flrp32 = true;
104*61046927SAndroid Build Coastguard Worker op.lower_flrp64 = true;
105*61046927SAndroid Build Coastguard Worker op.lower_fsqrt = dev.sm < 52;
106*61046927SAndroid Build Coastguard Worker op.lower_bitfield_extract = dev.sm >= 70;
107*61046927SAndroid Build Coastguard Worker op.lower_bitfield_insert = true;
108*61046927SAndroid Build Coastguard Worker op.lower_pack_half_2x16 = true;
109*61046927SAndroid Build Coastguard Worker op.lower_pack_unorm_2x16 = true;
110*61046927SAndroid Build Coastguard Worker op.lower_pack_snorm_2x16 = true;
111*61046927SAndroid Build Coastguard Worker op.lower_pack_unorm_4x8 = true;
112*61046927SAndroid Build Coastguard Worker op.lower_pack_snorm_4x8 = true;
113*61046927SAndroid Build Coastguard Worker op.lower_unpack_half_2x16 = true;
114*61046927SAndroid Build Coastguard Worker op.lower_unpack_unorm_2x16 = true;
115*61046927SAndroid Build Coastguard Worker op.lower_unpack_snorm_2x16 = true;
116*61046927SAndroid Build Coastguard Worker op.lower_unpack_unorm_4x8 = true;
117*61046927SAndroid Build Coastguard Worker op.lower_unpack_snorm_4x8 = true;
118*61046927SAndroid Build Coastguard Worker op.lower_insert_byte = true;
119*61046927SAndroid Build Coastguard Worker op.lower_insert_word = true;
120*61046927SAndroid Build Coastguard Worker op.lower_cs_local_index_to_id = true;
121*61046927SAndroid Build Coastguard Worker op.lower_device_index_to_zero = true;
122*61046927SAndroid Build Coastguard Worker op.lower_isign = true;
123*61046927SAndroid Build Coastguard Worker op.lower_uadd_sat = dev.sm < 70;
124*61046927SAndroid Build Coastguard Worker op.lower_usub_sat = dev.sm < 70;
125*61046927SAndroid Build Coastguard Worker op.lower_iadd_sat = true; // TODO
126*61046927SAndroid Build Coastguard Worker op.use_interpolated_input_intrinsics = true;
127*61046927SAndroid Build Coastguard Worker op.lower_doubles_options = nir_lower_drcp
128*61046927SAndroid Build Coastguard Worker | nir_lower_dsqrt
129*61046927SAndroid Build Coastguard Worker | nir_lower_drsq
130*61046927SAndroid Build Coastguard Worker | nir_lower_dtrunc
131*61046927SAndroid Build Coastguard Worker | nir_lower_dfloor
132*61046927SAndroid Build Coastguard Worker | nir_lower_dceil
133*61046927SAndroid Build Coastguard Worker | nir_lower_dfract
134*61046927SAndroid Build Coastguard Worker | nir_lower_dround_even
135*61046927SAndroid Build Coastguard Worker | nir_lower_dsat;
136*61046927SAndroid Build Coastguard Worker if dev.sm >= 70 {
137*61046927SAndroid Build Coastguard Worker op.lower_doubles_options |= nir_lower_dminmax;
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker op.lower_int64_options = !(nir_lower_icmp64
140*61046927SAndroid Build Coastguard Worker | nir_lower_iadd64
141*61046927SAndroid Build Coastguard Worker | nir_lower_ineg64
142*61046927SAndroid Build Coastguard Worker | nir_lower_shift64
143*61046927SAndroid Build Coastguard Worker | nir_lower_imul_2x32_64
144*61046927SAndroid Build Coastguard Worker | nir_lower_conv64);
145*61046927SAndroid Build Coastguard Worker op.lower_ldexp = true;
146*61046927SAndroid Build Coastguard Worker op.lower_fmod = true;
147*61046927SAndroid Build Coastguard Worker op.lower_ffract = true;
148*61046927SAndroid Build Coastguard Worker op.lower_fpow = true;
149*61046927SAndroid Build Coastguard Worker op.lower_scmp = true;
150*61046927SAndroid Build Coastguard Worker op.lower_uadd_carry = true;
151*61046927SAndroid Build Coastguard Worker op.lower_usub_borrow = true;
152*61046927SAndroid Build Coastguard Worker op.has_iadd3 = dev.sm >= 70;
153*61046927SAndroid Build Coastguard Worker op.has_imad32 = dev.sm >= 70;
154*61046927SAndroid Build Coastguard Worker op.has_sdot_4x8 = dev.sm >= 70;
155*61046927SAndroid Build Coastguard Worker op.has_udot_4x8 = dev.sm >= 70;
156*61046927SAndroid Build Coastguard Worker op.has_sudot_4x8 = dev.sm >= 70;
157*61046927SAndroid Build Coastguard Worker // We set .ftz on f32 by default so we can support fmulz whenever the client
158*61046927SAndroid Build Coastguard Worker // doesn't explicitly request denorms.
159*61046927SAndroid Build Coastguard Worker op.has_fmulz_no_denorms = true;
160*61046927SAndroid Build Coastguard Worker op.has_find_msb_rev = true;
161*61046927SAndroid Build Coastguard Worker op.has_pack_half_2x16_rtz = true;
162*61046927SAndroid Build Coastguard Worker op.has_bfm = dev.sm >= 70;
163*61046927SAndroid Build Coastguard Worker op.discard_is_demote = true;
164*61046927SAndroid Build Coastguard Worker
165*61046927SAndroid Build Coastguard Worker op.max_unroll_iterations = 32;
166*61046927SAndroid Build Coastguard Worker op.has_ddx_intrinsics = true;
167*61046927SAndroid Build Coastguard Worker op.scalarize_ddx = true;
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker op
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker
172*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_compiler_create( dev: *const nv_device_info, ) -> *mut nak_compiler173*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_compiler_create(
174*61046927SAndroid Build Coastguard Worker dev: *const nv_device_info,
175*61046927SAndroid Build Coastguard Worker ) -> *mut nak_compiler {
176*61046927SAndroid Build Coastguard Worker assert!(!dev.is_null());
177*61046927SAndroid Build Coastguard Worker let dev = unsafe { &*dev };
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker let nak = Box::new(nak_compiler {
180*61046927SAndroid Build Coastguard Worker sm: dev.sm,
181*61046927SAndroid Build Coastguard Worker warps_per_sm: dev.max_warps_per_mp,
182*61046927SAndroid Build Coastguard Worker nir_options: nir_options(dev),
183*61046927SAndroid Build Coastguard Worker });
184*61046927SAndroid Build Coastguard Worker
185*61046927SAndroid Build Coastguard Worker Box::into_raw(nak)
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker
188*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_compiler_destroy(nak: *mut nak_compiler)189*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_compiler_destroy(nak: *mut nak_compiler) {
190*61046927SAndroid Build Coastguard Worker unsafe { drop(Box::from_raw(nak)) };
191*61046927SAndroid Build Coastguard Worker }
192*61046927SAndroid Build Coastguard Worker
193*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_debug_flags(_nak: *const nak_compiler) -> u64194*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_debug_flags(_nak: *const nak_compiler) -> u64 {
195*61046927SAndroid Build Coastguard Worker DEBUG.debug_flags().into()
196*61046927SAndroid Build Coastguard Worker }
197*61046927SAndroid Build Coastguard Worker
198*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_nir_options( nak: *const nak_compiler, ) -> *const nir_shader_compiler_options199*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_nir_options(
200*61046927SAndroid Build Coastguard Worker nak: *const nak_compiler,
201*61046927SAndroid Build Coastguard Worker ) -> *const nir_shader_compiler_options {
202*61046927SAndroid Build Coastguard Worker assert!(!nak.is_null());
203*61046927SAndroid Build Coastguard Worker let nak = unsafe { &*nak };
204*61046927SAndroid Build Coastguard Worker &nak.nir_options
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker #[repr(C)]
208*61046927SAndroid Build Coastguard Worker pub struct ShaderBin {
209*61046927SAndroid Build Coastguard Worker bin: nak_shader_bin,
210*61046927SAndroid Build Coastguard Worker code: Vec<u32>,
211*61046927SAndroid Build Coastguard Worker asm: CString,
212*61046927SAndroid Build Coastguard Worker }
213*61046927SAndroid Build Coastguard Worker
214*61046927SAndroid Build Coastguard Worker impl ShaderBin {
new( sm: &dyn ShaderModel, info: &ShaderInfo, fs_key: Option<&nak_fs_key>, code: Vec<u32>, asm: &str, ) -> ShaderBin215*61046927SAndroid Build Coastguard Worker pub fn new(
216*61046927SAndroid Build Coastguard Worker sm: &dyn ShaderModel,
217*61046927SAndroid Build Coastguard Worker info: &ShaderInfo,
218*61046927SAndroid Build Coastguard Worker fs_key: Option<&nak_fs_key>,
219*61046927SAndroid Build Coastguard Worker code: Vec<u32>,
220*61046927SAndroid Build Coastguard Worker asm: &str,
221*61046927SAndroid Build Coastguard Worker ) -> ShaderBin {
222*61046927SAndroid Build Coastguard Worker let asm = CString::new(asm)
223*61046927SAndroid Build Coastguard Worker .expect("NAK assembly has unexpected null characters");
224*61046927SAndroid Build Coastguard Worker
225*61046927SAndroid Build Coastguard Worker let c_info = nak_shader_info {
226*61046927SAndroid Build Coastguard Worker stage: match info.stage {
227*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Compute(_) => MESA_SHADER_COMPUTE,
228*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Vertex => MESA_SHADER_VERTEX,
229*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Fragment(_) => MESA_SHADER_FRAGMENT,
230*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Geometry(_) => MESA_SHADER_GEOMETRY,
231*61046927SAndroid Build Coastguard Worker ShaderStageInfo::TessellationInit(_) => MESA_SHADER_TESS_CTRL,
232*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Tessellation(_) => MESA_SHADER_TESS_EVAL,
233*61046927SAndroid Build Coastguard Worker },
234*61046927SAndroid Build Coastguard Worker sm: sm.sm(),
235*61046927SAndroid Build Coastguard Worker num_gprs: if sm.sm() >= 70 {
236*61046927SAndroid Build Coastguard Worker max(4, info.num_gprs + 2)
237*61046927SAndroid Build Coastguard Worker } else {
238*61046927SAndroid Build Coastguard Worker max(4, info.num_gprs)
239*61046927SAndroid Build Coastguard Worker },
240*61046927SAndroid Build Coastguard Worker num_control_barriers: info.num_control_barriers,
241*61046927SAndroid Build Coastguard Worker _pad0: Default::default(),
242*61046927SAndroid Build Coastguard Worker num_instrs: info.num_instrs,
243*61046927SAndroid Build Coastguard Worker slm_size: info.slm_size,
244*61046927SAndroid Build Coastguard Worker crs_size: sm.crs_size(info.max_crs_depth),
245*61046927SAndroid Build Coastguard Worker __bindgen_anon_1: match &info.stage {
246*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Compute(cs_info) => {
247*61046927SAndroid Build Coastguard Worker nak_shader_info__bindgen_ty_1 {
248*61046927SAndroid Build Coastguard Worker cs: nak_shader_info__bindgen_ty_1__bindgen_ty_1 {
249*61046927SAndroid Build Coastguard Worker local_size: [
250*61046927SAndroid Build Coastguard Worker cs_info.local_size[0],
251*61046927SAndroid Build Coastguard Worker cs_info.local_size[1],
252*61046927SAndroid Build Coastguard Worker cs_info.local_size[2],
253*61046927SAndroid Build Coastguard Worker ],
254*61046927SAndroid Build Coastguard Worker smem_size: cs_info.smem_size,
255*61046927SAndroid Build Coastguard Worker _pad: Default::default(),
256*61046927SAndroid Build Coastguard Worker },
257*61046927SAndroid Build Coastguard Worker }
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Fragment(fs_info) => {
260*61046927SAndroid Build Coastguard Worker let fs_io_info = match &info.io {
261*61046927SAndroid Build Coastguard Worker ShaderIoInfo::Fragment(io) => io,
262*61046927SAndroid Build Coastguard Worker _ => unreachable!(),
263*61046927SAndroid Build Coastguard Worker };
264*61046927SAndroid Build Coastguard Worker nak_shader_info__bindgen_ty_1 {
265*61046927SAndroid Build Coastguard Worker fs: nak_shader_info__bindgen_ty_1__bindgen_ty_2 {
266*61046927SAndroid Build Coastguard Worker writes_depth: fs_io_info.writes_depth,
267*61046927SAndroid Build Coastguard Worker reads_sample_mask: fs_io_info.reads_sample_mask,
268*61046927SAndroid Build Coastguard Worker post_depth_coverage: fs_info.post_depth_coverage,
269*61046927SAndroid Build Coastguard Worker uses_sample_shading: fs_info.uses_sample_shading,
270*61046927SAndroid Build Coastguard Worker early_fragment_tests: fs_info.early_fragment_tests,
271*61046927SAndroid Build Coastguard Worker _pad: Default::default(),
272*61046927SAndroid Build Coastguard Worker },
273*61046927SAndroid Build Coastguard Worker }
274*61046927SAndroid Build Coastguard Worker }
275*61046927SAndroid Build Coastguard Worker ShaderStageInfo::Tessellation(ts_info) => {
276*61046927SAndroid Build Coastguard Worker nak_shader_info__bindgen_ty_1 {
277*61046927SAndroid Build Coastguard Worker ts: nak_shader_info__bindgen_ty_1__bindgen_ty_3 {
278*61046927SAndroid Build Coastguard Worker domain: ts_info.domain as u8,
279*61046927SAndroid Build Coastguard Worker spacing: ts_info.spacing as u8,
280*61046927SAndroid Build Coastguard Worker prims: ts_info.primitives as u8,
281*61046927SAndroid Build Coastguard Worker _pad: Default::default(),
282*61046927SAndroid Build Coastguard Worker },
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker }
285*61046927SAndroid Build Coastguard Worker _ => nak_shader_info__bindgen_ty_1 {
286*61046927SAndroid Build Coastguard Worker _pad: Default::default(),
287*61046927SAndroid Build Coastguard Worker },
288*61046927SAndroid Build Coastguard Worker },
289*61046927SAndroid Build Coastguard Worker vtg: match &info.io {
290*61046927SAndroid Build Coastguard Worker ShaderIoInfo::Vtg(io) => nak_shader_info__bindgen_ty_2 {
291*61046927SAndroid Build Coastguard Worker writes_layer: io.attr_written(NAK_ATTR_RT_ARRAY_INDEX),
292*61046927SAndroid Build Coastguard Worker writes_point_size: io.attr_written(NAK_ATTR_POINT_SIZE),
293*61046927SAndroid Build Coastguard Worker clip_enable: io.clip_enable.try_into().unwrap(),
294*61046927SAndroid Build Coastguard Worker cull_enable: io.cull_enable.try_into().unwrap(),
295*61046927SAndroid Build Coastguard Worker xfb: if let Some(xfb) = &io.xfb {
296*61046927SAndroid Build Coastguard Worker **xfb
297*61046927SAndroid Build Coastguard Worker } else {
298*61046927SAndroid Build Coastguard Worker unsafe { std::mem::zeroed() }
299*61046927SAndroid Build Coastguard Worker },
300*61046927SAndroid Build Coastguard Worker },
301*61046927SAndroid Build Coastguard Worker _ => unsafe { std::mem::zeroed() },
302*61046927SAndroid Build Coastguard Worker },
303*61046927SAndroid Build Coastguard Worker hdr: sph::encode_header(sm, &info, fs_key),
304*61046927SAndroid Build Coastguard Worker };
305*61046927SAndroid Build Coastguard Worker
306*61046927SAndroid Build Coastguard Worker if DEBUG.print() {
307*61046927SAndroid Build Coastguard Worker let stage_name = unsafe {
308*61046927SAndroid Build Coastguard Worker let c_name = _mesa_shader_stage_to_string(c_info.stage as u32);
309*61046927SAndroid Build Coastguard Worker CStr::from_ptr(c_name).to_str().expect("Invalid UTF-8")
310*61046927SAndroid Build Coastguard Worker };
311*61046927SAndroid Build Coastguard Worker
312*61046927SAndroid Build Coastguard Worker eprintln!("Stage: {}", stage_name);
313*61046927SAndroid Build Coastguard Worker eprintln!("Instruction count: {}", c_info.num_instrs);
314*61046927SAndroid Build Coastguard Worker eprintln!("Num GPRs: {}", c_info.num_gprs);
315*61046927SAndroid Build Coastguard Worker eprintln!("SLM size: {}", c_info.slm_size);
316*61046927SAndroid Build Coastguard Worker
317*61046927SAndroid Build Coastguard Worker if c_info.stage != MESA_SHADER_COMPUTE {
318*61046927SAndroid Build Coastguard Worker eprint_hex("Header", &c_info.hdr);
319*61046927SAndroid Build Coastguard Worker }
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Worker eprint_hex("Encoded shader", &code);
322*61046927SAndroid Build Coastguard Worker }
323*61046927SAndroid Build Coastguard Worker
324*61046927SAndroid Build Coastguard Worker let bin = nak_shader_bin {
325*61046927SAndroid Build Coastguard Worker info: c_info,
326*61046927SAndroid Build Coastguard Worker code_size: (code.len() * 4).try_into().unwrap(),
327*61046927SAndroid Build Coastguard Worker code: code.as_ptr() as *const c_void,
328*61046927SAndroid Build Coastguard Worker asm_str: if asm.is_empty() {
329*61046927SAndroid Build Coastguard Worker std::ptr::null()
330*61046927SAndroid Build Coastguard Worker } else {
331*61046927SAndroid Build Coastguard Worker asm.as_ptr()
332*61046927SAndroid Build Coastguard Worker },
333*61046927SAndroid Build Coastguard Worker };
334*61046927SAndroid Build Coastguard Worker ShaderBin {
335*61046927SAndroid Build Coastguard Worker bin: bin,
336*61046927SAndroid Build Coastguard Worker code: code,
337*61046927SAndroid Build Coastguard Worker asm: asm,
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker }
340*61046927SAndroid Build Coastguard Worker }
341*61046927SAndroid Build Coastguard Worker
342*61046927SAndroid Build Coastguard Worker impl std::ops::Deref for ShaderBin {
343*61046927SAndroid Build Coastguard Worker type Target = nak_shader_bin;
344*61046927SAndroid Build Coastguard Worker
deref(&self) -> &nak_shader_bin345*61046927SAndroid Build Coastguard Worker fn deref(&self) -> &nak_shader_bin {
346*61046927SAndroid Build Coastguard Worker &self.bin
347*61046927SAndroid Build Coastguard Worker }
348*61046927SAndroid Build Coastguard Worker }
349*61046927SAndroid Build Coastguard Worker
350*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_shader_bin_destroy(bin: *mut nak_shader_bin)351*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_shader_bin_destroy(bin: *mut nak_shader_bin) {
352*61046927SAndroid Build Coastguard Worker unsafe {
353*61046927SAndroid Build Coastguard Worker _ = Box::from_raw(bin as *mut ShaderBin);
354*61046927SAndroid Build Coastguard Worker };
355*61046927SAndroid Build Coastguard Worker }
356*61046927SAndroid Build Coastguard Worker
eprint_hex(label: &str, data: &[u32])357*61046927SAndroid Build Coastguard Worker fn eprint_hex(label: &str, data: &[u32]) {
358*61046927SAndroid Build Coastguard Worker eprint!("{}:", label);
359*61046927SAndroid Build Coastguard Worker for i in 0..data.len() {
360*61046927SAndroid Build Coastguard Worker if (i % 8) == 0 {
361*61046927SAndroid Build Coastguard Worker eprintln!("");
362*61046927SAndroid Build Coastguard Worker eprint!(" ");
363*61046927SAndroid Build Coastguard Worker }
364*61046927SAndroid Build Coastguard Worker eprint!(" {:08x}", data[i]);
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker eprintln!("");
367*61046927SAndroid Build Coastguard Worker }
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker macro_rules! pass {
370*61046927SAndroid Build Coastguard Worker ($s: expr, $pass: ident) => {
371*61046927SAndroid Build Coastguard Worker $s.$pass();
372*61046927SAndroid Build Coastguard Worker if DEBUG.print() {
373*61046927SAndroid Build Coastguard Worker eprintln!("NAK IR after {}:\n{}", stringify!($pass), $s);
374*61046927SAndroid Build Coastguard Worker }
375*61046927SAndroid Build Coastguard Worker };
376*61046927SAndroid Build Coastguard Worker }
377*61046927SAndroid Build Coastguard Worker
378*61046927SAndroid Build Coastguard Worker #[no_mangle]
nak_compile_shader( nir: *mut nir_shader, dump_asm: bool, nak: *const nak_compiler, robust2_modes: nir_variable_mode, fs_key: *const nak_fs_key, ) -> *mut nak_shader_bin379*61046927SAndroid Build Coastguard Worker pub extern "C" fn nak_compile_shader(
380*61046927SAndroid Build Coastguard Worker nir: *mut nir_shader,
381*61046927SAndroid Build Coastguard Worker dump_asm: bool,
382*61046927SAndroid Build Coastguard Worker nak: *const nak_compiler,
383*61046927SAndroid Build Coastguard Worker robust2_modes: nir_variable_mode,
384*61046927SAndroid Build Coastguard Worker fs_key: *const nak_fs_key,
385*61046927SAndroid Build Coastguard Worker ) -> *mut nak_shader_bin {
386*61046927SAndroid Build Coastguard Worker unsafe { nak_postprocess_nir(nir, nak, robust2_modes, fs_key) };
387*61046927SAndroid Build Coastguard Worker let nak = unsafe { &*nak };
388*61046927SAndroid Build Coastguard Worker let nir = unsafe { &*nir };
389*61046927SAndroid Build Coastguard Worker let fs_key = if fs_key.is_null() {
390*61046927SAndroid Build Coastguard Worker None
391*61046927SAndroid Build Coastguard Worker } else {
392*61046927SAndroid Build Coastguard Worker Some(unsafe { &*fs_key })
393*61046927SAndroid Build Coastguard Worker };
394*61046927SAndroid Build Coastguard Worker
395*61046927SAndroid Build Coastguard Worker let sm: Box<dyn ShaderModel> = if nak.sm >= 70 {
396*61046927SAndroid Build Coastguard Worker Box::new(ShaderModel70::new(nak.sm))
397*61046927SAndroid Build Coastguard Worker } else if nak.sm >= 50 {
398*61046927SAndroid Build Coastguard Worker Box::new(ShaderModel50::new(nak.sm))
399*61046927SAndroid Build Coastguard Worker } else {
400*61046927SAndroid Build Coastguard Worker panic!("Unsupported shader model");
401*61046927SAndroid Build Coastguard Worker };
402*61046927SAndroid Build Coastguard Worker
403*61046927SAndroid Build Coastguard Worker let mut s = nak_shader_from_nir(nir, sm.as_ref());
404*61046927SAndroid Build Coastguard Worker
405*61046927SAndroid Build Coastguard Worker if DEBUG.print() {
406*61046927SAndroid Build Coastguard Worker eprintln!("NAK IR:\n{}", &s);
407*61046927SAndroid Build Coastguard Worker }
408*61046927SAndroid Build Coastguard Worker
409*61046927SAndroid Build Coastguard Worker pass!(s, opt_bar_prop);
410*61046927SAndroid Build Coastguard Worker pass!(s, opt_uniform_instrs);
411*61046927SAndroid Build Coastguard Worker pass!(s, opt_copy_prop);
412*61046927SAndroid Build Coastguard Worker pass!(s, opt_prmt);
413*61046927SAndroid Build Coastguard Worker pass!(s, opt_lop);
414*61046927SAndroid Build Coastguard Worker pass!(s, opt_copy_prop);
415*61046927SAndroid Build Coastguard Worker pass!(s, opt_dce);
416*61046927SAndroid Build Coastguard Worker pass!(s, opt_out);
417*61046927SAndroid Build Coastguard Worker pass!(s, legalize);
418*61046927SAndroid Build Coastguard Worker pass!(s, assign_regs);
419*61046927SAndroid Build Coastguard Worker pass!(s, lower_par_copies);
420*61046927SAndroid Build Coastguard Worker pass!(s, lower_copy_swap);
421*61046927SAndroid Build Coastguard Worker if nak.sm >= 70 {
422*61046927SAndroid Build Coastguard Worker pass!(s, opt_jump_thread);
423*61046927SAndroid Build Coastguard Worker } else {
424*61046927SAndroid Build Coastguard Worker pass!(s, opt_crs);
425*61046927SAndroid Build Coastguard Worker }
426*61046927SAndroid Build Coastguard Worker pass!(s, calc_instr_deps);
427*61046927SAndroid Build Coastguard Worker
428*61046927SAndroid Build Coastguard Worker s.gather_info();
429*61046927SAndroid Build Coastguard Worker
430*61046927SAndroid Build Coastguard Worker let mut asm = String::new();
431*61046927SAndroid Build Coastguard Worker if dump_asm {
432*61046927SAndroid Build Coastguard Worker write!(asm, "{}", s).expect("Failed to dump assembly");
433*61046927SAndroid Build Coastguard Worker }
434*61046927SAndroid Build Coastguard Worker
435*61046927SAndroid Build Coastguard Worker s.remove_annotations();
436*61046927SAndroid Build Coastguard Worker
437*61046927SAndroid Build Coastguard Worker let code = sm.encode_shader(&s);
438*61046927SAndroid Build Coastguard Worker let bin =
439*61046927SAndroid Build Coastguard Worker Box::new(ShaderBin::new(sm.as_ref(), &s.info, fs_key, code, &asm));
440*61046927SAndroid Build Coastguard Worker Box::into_raw(bin) as *mut nak_shader_bin
441*61046927SAndroid Build Coastguard Worker }
442