Module: Mesa Branch: main Commit: 94d96dac601ff2126996ac37a0b637961d06dfab URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=94d96dac601ff2126996ac37a0b637961d06dfab
Author: Faith Ekstrand <faith.ekstr...@collabora.com> Date: Mon Jan 8 17:50:26 2024 -0600 nak: Add explicit padding to nak_shader_info This ensures that the padding bits stay zero, even as we copy the structure around through multiple languages. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27049> --- src/nouveau/compiler/meson.build | 2 ++ src/nouveau/compiler/nak.h | 26 +++++++++++++++++++++++++- src/nouveau/compiler/nak/api.rs | 31 ++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/nouveau/compiler/meson.build b/src/nouveau/compiler/meson.build index 535294ecf1f..f8a55046edb 100644 --- a/src/nouveau/compiler/meson.build +++ b/src/nouveau/compiler/meson.build @@ -78,11 +78,13 @@ nak_bindings_rs = rust.bindgen( '--allowlist-type', 'mesa_scope', '--allowlist-type', 'mesa_prim', '--allowlist-type', 'tess_primitive_mode', + '--allowlist-var', 'NAK_.*', '--allowlist-var', 'nir_.*_infos', '--allowlist-function', '_mesa_shader_stage_to_string', '--allowlist-function', 'nak_.*', '--allowlist-function', 'nir_.*', '--allowlist-function', 'glsl_.*', + '--explicit-padding', '--no-prepend-enum-name', ], dependencies : libnak_deps, diff --git a/src/nouveau/compiler/nak.h b/src/nouveau/compiler/nak.h index 5a3cf249401..cfec9e4f738 100644 --- a/src/nouveau/compiler/nak.h +++ b/src/nouveau/compiler/nak.h @@ -79,6 +79,20 @@ struct nak_xfb_info { uint8_t attr_index[4][128]; }; +/* This is an enum so bindgen will generate it */ +#define NAK_SHADER_INFO_STAGE_UNION_SIZE 12 + +/* This struct MUST have explicit padding fields to ensure that all padding is + * zeroed and the zeros get properly copied, even across API boundaries. This + * is ensured in two ways: + * + * - Bindgen is invoked with --explicit-padding and if a __bindgen_paddingN + * member ever crops up, that tells us we need to add an explicit member + * here. + * + * - There is a set of const asserts in nak/api.rs which ensure that all of + * the union fields are equal to NAK_SHADER_INFO_STAGE_UNION_SIZE. + */ struct nak_shader_info { gl_shader_stage stage; @@ -88,6 +102,8 @@ struct nak_shader_info { /** Number of barriers used */ uint8_t num_barriers; + uint16_t _pad0; + /** Size of shader local (scratch) memory */ uint32_t slm_size; @@ -98,6 +114,8 @@ struct nak_shader_info { /* Shared memory size */ uint16_t smem_size; + + uint8_t _pad[4]; } cs; struct { @@ -106,16 +124,20 @@ struct nak_shader_info { bool post_depth_coverage; bool uses_sample_shading; bool early_fragment_tests; + + uint8_t _pad[7]; } fs; struct { enum nak_ts_domain domain; enum nak_ts_spacing spacing; enum nak_ts_prims prims; + + uint8_t _pad[9]; } ts; /* Used to initialize the union for other stages */ - uint32_t dummy; + uint8_t _pad[NAK_SHADER_INFO_STAGE_UNION_SIZE]; }; struct { @@ -123,6 +145,8 @@ struct nak_shader_info { uint8_t clip_enable; uint8_t cull_enable; + uint8_t _pad[1]; + struct nak_xfb_info xfb; } vtg; diff --git a/src/nouveau/compiler/nak/api.rs b/src/nouveau/compiler/nak/api.rs index 69ceb774feb..35fad6f2aa2 100644 --- a/src/nouveau/compiler/nak/api.rs +++ b/src/nouveau/compiler/nak/api.rs @@ -154,6 +154,7 @@ pub extern "C" fn nak_compiler_create( let nak = Box::new(nak_compiler { sm: dev.sm, nir_options: nir_options(dev), + ..unsafe { std::mem::zeroed() } }); Box::into_raw(nak) @@ -198,6 +199,7 @@ impl ShaderBin { } else { asm.as_ptr() }, + ..unsafe { std::mem::zeroed() } }; ShaderBin { bin: bin, @@ -226,6 +228,25 @@ fn eprint_hex(label: &str, data: &[u32]) { eprintln!(""); } +const _: () = { + assert!( + std::mem::size_of::<nak_shader_info__bindgen_ty_1>() + == NAK_SHADER_INFO_STAGE_UNION_SIZE as usize + ); + assert!( + std::mem::size_of::<nak_shader_info__bindgen_ty_1__bindgen_ty_1>() + == NAK_SHADER_INFO_STAGE_UNION_SIZE as usize + ); + assert!( + std::mem::size_of::<nak_shader_info__bindgen_ty_1__bindgen_ty_2>() + == NAK_SHADER_INFO_STAGE_UNION_SIZE as usize + ); + assert!( + std::mem::size_of::<nak_shader_info__bindgen_ty_1__bindgen_ty_2>() + == NAK_SHADER_INFO_STAGE_UNION_SIZE as usize + ); +}; + #[no_mangle] pub extern "C" fn nak_compile_shader( nir: *mut nir_shader, @@ -304,6 +325,7 @@ pub extern "C" fn nak_compile_shader( max(4, s.info.num_gprs) }, num_barriers: s.info.num_barriers, + _pad0: Default::default(), slm_size: s.info.slm_size, __bindgen_anon_1: match &s.info.stage { ShaderStageInfo::Compute(cs_info) => { @@ -315,6 +337,7 @@ pub extern "C" fn nak_compile_shader( cs_info.local_size[2], ], smem_size: cs_info.smem_size, + _pad: Default::default(), }, } } @@ -333,6 +356,7 @@ pub extern "C" fn nak_compile_shader( uses_sample_shading: nir_fs_info.uses_sample_shading(), early_fragment_tests: nir_fs_info .early_fragment_tests(), + _pad: Default::default(), }, } } @@ -369,10 +393,14 @@ pub extern "C" fn nak_compile_shader( } else { NAK_TS_PRIMS_TRIANGLES_CW }, + + _pad: Default::default(), }, } } - _ => nak_shader_info__bindgen_ty_1 { dummy: 0 }, + _ => nak_shader_info__bindgen_ty_1 { + _pad: Default::default(), + }, }, vtg: match &s.info.stage { ShaderStageInfo::Geometry(_) @@ -388,6 +416,7 @@ pub extern "C" fn nak_compile_shader( writes_layer: writes_layer, clip_enable: clip_enable.try_into().unwrap(), cull_enable: cull_enable.try_into().unwrap(), + _pad: Default::default(), xfb: unsafe { nak_xfb_from_nir(nir.xfb_info) }, } }