Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_vsc.c
4574 views
/*1* Copyright © 2020 Google, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*/2223#include "pipe/p_state.h"24#include "util/u_prim.h"2526#include "freedreno_batch.h"27#include "freedreno_gmem.h"2829#include "fd6_vsc.h"3031/*32* Helper util to update expected vsc draw and primitive stream sizes, see33* https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format34*/3536enum {37byte = 8,38dword = 4 * byte,39} bits_per;4041/**42* Determine # of bits required to store a given number, see43* https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#numbers44*/45static unsigned46number_size_bits(unsigned nr)47{48unsigned n = util_last_bit(nr);49assert(n); /* encoding 0 is not possible */50return n + (n - 1);51}5253/**54* Determine # of bits requred to store a given bitfield, see55* https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#bitfields56*/57static unsigned58bitfield_size_bits(unsigned n)59{60return n + 1; /* worst case is always 1 + nr of bits */61}6263static unsigned64prim_count(const struct pipe_draw_info *info,65const struct pipe_draw_start_count_bias *draw)66{67/* PIPE_PRIM_MAX used internally for RECTLIST blits on 3d pipe: */68unsigned vtx_per_prim =69(info->mode == PIPE_PRIM_MAX) ? 2 : u_vertices_per_prim(info->mode);70return MAX2(1, (draw->count * info->instance_count) / vtx_per_prim);71}7273/**74* The primitive stream uses a run-length encoding, where each packet contains a75* bitfield of bins covered and then the number of primitives which have the76* same bitfield. Each packet consists of the following, in order:77*78* - The (compressed) bitfield of bins covered79* - The number of primitives with this bitset80* - Checksum81*82* The worst case would be that each primitive has a different bitmask. In83* practice, assuming ever other primitive has a different bitmask still gets us84* conservatively large primitive stream sizes. (Ie. 10x what is needed, vs.85* 20x)86*87* https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#primitive-streams88*/89static unsigned90primitive_stream_size_bits(const struct pipe_draw_info *info,91const struct pipe_draw_start_count_bias *draw,92unsigned num_bins)93{94unsigned num_prims = prim_count(info, draw);95unsigned nbits =96(bitfield_size_bits(num_bins) /* bitfield of bins covered */97+ number_size_bits(1) /* number of primitives with this bitset */98+ 1 /* checksum */99) *100DIV_ROUND_UP(num_prims, 2);101return align(nbits, dword);102}103104/**105* Each draw stream packet contains the following:106*107* - Bin bitfield108* - Last instance bit109* - If bitfield is empty, the number of draws it is empty for, otherwise110* the size of the corresponding primitive stream in DWORD's.111* - Checksum112*113* https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#draw-streams114*/115static unsigned116draw_stream_size_bits(const struct pipe_draw_info *info, unsigned num_bins,117unsigned prim_strm_bits)118{119unsigned ndwords = prim_strm_bits / dword;120return (bitfield_size_bits(num_bins) /* bitfield of bins */121+ 1 /* last-instance-bit */122+ number_size_bits(ndwords) /* size of corresponding prim strm */123+ 1 /* checksum */124) *125MAX2(1, info->instance_count);126}127128void129fd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info,130const struct pipe_draw_start_count_bias *draw)131{132if (!batch->num_bins_per_pipe) {133batch->num_bins_per_pipe = fd_gmem_estimate_bins_per_pipe(batch);134135/* This is a convenient spot to add the size of the final draw-136* stream packet:137*138* If there are N bins, the final packet, after all the draws are139* done, consists of a 1 followed by N + 17 0's, plus a final 1.140* This uses the otherwise-unused pattern of a non-empty bitfield141* (initial 1) that is nontheless empty (has all 0's)142*/143unsigned final_pkt_sz = 1 + batch->num_bins_per_pipe + 17 + 1;144batch->prim_strm_bits = align(final_pkt_sz, dword);145}146147unsigned prim_strm_bits =148primitive_stream_size_bits(info, draw, batch->num_bins_per_pipe);149unsigned draw_strm_bits =150draw_stream_size_bits(info, batch->num_bins_per_pipe, prim_strm_bits);151152#if 0153mesa_logd("vsc: prim_strm_bits=%d, draw_strm_bits=%d, nb=%u, ic=%u, c=%u, pc=%u (%s)",154prim_strm_bits, draw_strm_bits, batch->num_bins_per_pipe,155info->instance_count, info->count,156(info->count * info->instance_count) /157u_vertices_per_prim(info->mode),158u_prim_name(info->mode));159#endif160161batch->prim_strm_bits += prim_strm_bits;162batch->draw_strm_bits += draw_strm_bits;163}164165166