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