1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2020 Google, Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "pipe/p_state.h" 25bf215546Sopenharmony_ci#include "util/u_prim.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "freedreno_batch.h" 28bf215546Sopenharmony_ci#include "freedreno_gmem.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "fd6_vsc.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci/* 33bf215546Sopenharmony_ci * Helper util to update expected vsc draw and primitive stream sizes, see 34bf215546Sopenharmony_ci * https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format 35bf215546Sopenharmony_ci */ 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cienum bits_per { 38bf215546Sopenharmony_ci byte = 8, 39bf215546Sopenharmony_ci dword = 4 * byte, 40bf215546Sopenharmony_ci}; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci/** 43bf215546Sopenharmony_ci * Determine # of bits required to store a given number, see 44bf215546Sopenharmony_ci * https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#numbers 45bf215546Sopenharmony_ci */ 46bf215546Sopenharmony_cistatic unsigned 47bf215546Sopenharmony_cinumber_size_bits(unsigned nr) 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci unsigned n = util_last_bit(nr); 50bf215546Sopenharmony_ci assert(n); /* encoding 0 is not possible */ 51bf215546Sopenharmony_ci return n + (n - 1); 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/** 55bf215546Sopenharmony_ci * Determine # of bits requred to store a given bitfield, see 56bf215546Sopenharmony_ci * https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#bitfields 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_cistatic unsigned 59bf215546Sopenharmony_cibitfield_size_bits(unsigned n) 60bf215546Sopenharmony_ci{ 61bf215546Sopenharmony_ci return n + 1; /* worst case is always 1 + nr of bits */ 62bf215546Sopenharmony_ci} 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistatic unsigned 65bf215546Sopenharmony_ciprim_count(const struct pipe_draw_info *info, 66bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci /* PIPE_PRIM_MAX used internally for RECTLIST blits on 3d pipe: */ 69bf215546Sopenharmony_ci unsigned vtx_per_prim = 70bf215546Sopenharmony_ci (info->mode == PIPE_PRIM_MAX) ? 2 : u_vertices_per_prim(info->mode); 71bf215546Sopenharmony_ci return MAX2(1, (draw->count * info->instance_count) / vtx_per_prim); 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci/** 75bf215546Sopenharmony_ci * The primitive stream uses a run-length encoding, where each packet contains a 76bf215546Sopenharmony_ci * bitfield of bins covered and then the number of primitives which have the 77bf215546Sopenharmony_ci * same bitfield. Each packet consists of the following, in order: 78bf215546Sopenharmony_ci * 79bf215546Sopenharmony_ci * - The (compressed) bitfield of bins covered 80bf215546Sopenharmony_ci * - The number of primitives with this bitset 81bf215546Sopenharmony_ci * - Checksum 82bf215546Sopenharmony_ci * 83bf215546Sopenharmony_ci * The worst case would be that each primitive has a different bitmask. In 84bf215546Sopenharmony_ci * practice, assuming ever other primitive has a different bitmask still gets us 85bf215546Sopenharmony_ci * conservatively large primitive stream sizes. (Ie. 10x what is needed, vs. 86bf215546Sopenharmony_ci * 20x) 87bf215546Sopenharmony_ci * 88bf215546Sopenharmony_ci * https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#primitive-streams 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_cistatic unsigned 91bf215546Sopenharmony_ciprimitive_stream_size_bits(const struct pipe_draw_info *info, 92bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 93bf215546Sopenharmony_ci unsigned num_bins) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci unsigned num_prims = prim_count(info, draw); 96bf215546Sopenharmony_ci unsigned nbits = 97bf215546Sopenharmony_ci (bitfield_size_bits(num_bins) /* bitfield of bins covered */ 98bf215546Sopenharmony_ci + number_size_bits(1) /* number of primitives with this bitset */ 99bf215546Sopenharmony_ci + 1 /* checksum */ 100bf215546Sopenharmony_ci ) * 101bf215546Sopenharmony_ci DIV_ROUND_UP(num_prims, 2); 102bf215546Sopenharmony_ci return align(nbits, dword); 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci/** 106bf215546Sopenharmony_ci * Each draw stream packet contains the following: 107bf215546Sopenharmony_ci * 108bf215546Sopenharmony_ci * - Bin bitfield 109bf215546Sopenharmony_ci * - Last instance bit 110bf215546Sopenharmony_ci * - If bitfield is empty, the number of draws it is empty for, otherwise 111bf215546Sopenharmony_ci * the size of the corresponding primitive stream in DWORD's. 112bf215546Sopenharmony_ci * - Checksum 113bf215546Sopenharmony_ci * 114bf215546Sopenharmony_ci * https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#draw-streams 115bf215546Sopenharmony_ci */ 116bf215546Sopenharmony_cistatic unsigned 117bf215546Sopenharmony_cidraw_stream_size_bits(const struct pipe_draw_info *info, unsigned num_bins, 118bf215546Sopenharmony_ci unsigned prim_strm_bits) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci unsigned ndwords = prim_strm_bits / dword; 121bf215546Sopenharmony_ci return (bitfield_size_bits(num_bins) /* bitfield of bins */ 122bf215546Sopenharmony_ci + 1 /* last-instance-bit */ 123bf215546Sopenharmony_ci + number_size_bits(ndwords) /* size of corresponding prim strm */ 124bf215546Sopenharmony_ci + 1 /* checksum */ 125bf215546Sopenharmony_ci ) * 126bf215546Sopenharmony_ci MAX2(1, info->instance_count); 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_civoid 130bf215546Sopenharmony_cifd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info, 131bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci if (!batch->num_bins_per_pipe) { 134bf215546Sopenharmony_ci batch->num_bins_per_pipe = fd_gmem_estimate_bins_per_pipe(batch); 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci /* This is a convenient spot to add the size of the final draw- 137bf215546Sopenharmony_ci * stream packet: 138bf215546Sopenharmony_ci * 139bf215546Sopenharmony_ci * If there are N bins, the final packet, after all the draws are 140bf215546Sopenharmony_ci * done, consists of a 1 followed by N + 17 0's, plus a final 1. 141bf215546Sopenharmony_ci * This uses the otherwise-unused pattern of a non-empty bitfield 142bf215546Sopenharmony_ci * (initial 1) that is nontheless empty (has all 0's) 143bf215546Sopenharmony_ci */ 144bf215546Sopenharmony_ci unsigned final_pkt_sz = 1 + batch->num_bins_per_pipe + 17 + 1; 145bf215546Sopenharmony_ci batch->prim_strm_bits = align(final_pkt_sz, dword); 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci unsigned prim_strm_bits = 149bf215546Sopenharmony_ci primitive_stream_size_bits(info, draw, batch->num_bins_per_pipe); 150bf215546Sopenharmony_ci unsigned draw_strm_bits = 151bf215546Sopenharmony_ci draw_stream_size_bits(info, batch->num_bins_per_pipe, prim_strm_bits); 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci#if 0 154bf215546Sopenharmony_ci mesa_logd("vsc: prim_strm_bits=%d, draw_strm_bits=%d, nb=%u, ic=%u, c=%u, pc=%u (%s)", 155bf215546Sopenharmony_ci prim_strm_bits, draw_strm_bits, batch->num_bins_per_pipe, 156bf215546Sopenharmony_ci info->instance_count, info->count, 157bf215546Sopenharmony_ci (info->count * info->instance_count) / 158bf215546Sopenharmony_ci u_vertices_per_prim(info->mode), 159bf215546Sopenharmony_ci u_prim_name(info->mode)); 160bf215546Sopenharmony_ci#endif 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci batch->prim_strm_bits += prim_strm_bits; 163bf215546Sopenharmony_ci batch->draw_strm_bits += draw_strm_bits; 164bf215546Sopenharmony_ci} 165