diff --git a/src/nouveau/compiler/nak.h b/src/nouveau/compiler/nak.h index 9faa73d0325..0bf07953cfd 100644 --- a/src/nouveau/compiler/nak.h +++ b/src/nouveau/compiler/nak.h @@ -44,6 +44,13 @@ struct nak_fs_key { void nak_postprocess_nir(nir_shader *nir, const struct nak_compiler *nak, const struct nak_fs_key *fs_key); +struct nvk_xfb_info { + uint32_t stride[4]; + uint8_t stream[4]; + uint8_t attr_count[4]; + uint8_t attr_index[4][128]; +}; + struct nak_shader_info { gl_shader_stage stage; @@ -77,6 +84,8 @@ struct nak_shader_info { uint32_t dummy; }; + struct nvk_xfb_info xfb; + /** Shader header for 3D stages */ uint32_t hdr[32]; }; diff --git a/src/nouveau/compiler/nak.rs b/src/nouveau/compiler/nak.rs index f4051bc1a3c..3e11d2bbcb8 100644 --- a/src/nouveau/compiler/nak.rs +++ b/src/nouveau/compiler/nak.rs @@ -315,6 +315,7 @@ pub extern "C" fn nak_compile_shader( } _ => nak_shader_info__bindgen_ty_1 { dummy: 0 }, }, + xfb: unsafe { nak_xfb_from_nir(nir.xfb_info) }, hdr: nak_sph::encode_header(&s.info, fs_key), }; diff --git a/src/nouveau/compiler/nak_nir.c b/src/nouveau/compiler/nak_nir.c index b8904161e11..f9fba03eb30 100644 --- a/src/nouveau/compiler/nak_nir.c +++ b/src/nouveau/compiler/nak_nir.c @@ -5,6 +5,7 @@ #include "nak_private.h" #include "nir_builder.h" +#include "nir_xfb_info.h" #include "util/u_math.h" @@ -317,6 +318,40 @@ nak_nir_lower_varyings(nir_shader *nir, nir_variable_mode modes) return progress; } +struct nvk_xfb_info +nak_xfb_from_nir(const struct nir_xfb_info *nir_xfb) +{ + if (nir_xfb == NULL) + return (struct nvk_xfb_info) { }; + + struct nvk_xfb_info nak_xfb = { }; + + u_foreach_bit(b, nir_xfb->buffers_written) { + nak_xfb.stride[b] = nir_xfb->buffers[b].stride; + nak_xfb.stream[b] = nir_xfb->buffer_to_stream[b]; + } + + for (unsigned o = 0; o < nir_xfb->output_count; o++) { + const nir_xfb_output_info *out = &nir_xfb->outputs[o]; + const uint8_t b = out->buffer; + assert(nir_xfb->buffers_written & BITFIELD_BIT(b)); + + const uint16_t attr_addr = nak_varying_attr_addr(out->location); + assert(attr_addr % 4 == 0); + const uint16_t attr_idx = attr_addr / 4; + + assert(out->offset % 4 == 0); + uint8_t out_idx = out->offset / 4; + + u_foreach_bit(c, out->component_mask) + nak_xfb.attr_index[b][out_idx++] = attr_idx + c; + + nak_xfb.attr_count[b] = MAX2(nak_xfb.attr_count[b], out_idx); + } + + return nak_xfb; +} + static nir_def * load_frag_w(nir_builder *b, nir_def *bary) { diff --git a/src/nouveau/compiler/nak_private.h b/src/nouveau/compiler/nak_private.h index 7e34270f4c2..eb9bf66d076 100644 --- a/src/nouveau/compiler/nak_private.h +++ b/src/nouveau/compiler/nak_private.h @@ -22,6 +22,9 @@ struct nak_compiler { struct nir_shader_compiler_options nir_options; }; +struct nvk_xfb_info +nak_xfb_from_nir(const struct nir_xfb_info *nir_xfb); + struct nak_io_addr_offset { nir_scalar base; int32_t offset;