1 /*
2 * Copyright © 2020 Google, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <getopt.h>
25 #include <stdbool.h>
26
27 static bool bin_debug = false;
28 #define BIN_DEBUG bin_debug
29
30 #include "freedreno_gmem.c"
31
32 /* NOTE, non-interesting gmem keys (ie. things that are small enough to fit
33 * in a single bin) are commented out, but retained for posterity.
34 */
35 /* clang-format off */
36 static const struct gmem_key keys[] = {
37 { .minx=0, .miny=0, .width=1536, .height=2048, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {1,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
38 /* manhattan: */
39 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
40 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
41 // { .minx=0, .miny=0, .width=64, .height=64, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
42 // { .minx=0, .miny=0, .width=32, .height=32, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
43 // { .minx=0, .miny=0, .width=16, .height=16, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
44 // { .minx=0, .miny=0, .width=8, .height=8, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
45 // { .minx=0, .miny=0, .width=4, .height=4, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
46 // { .minx=0, .miny=0, .width=2, .height=2, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
47 // { .minx=0, .miny=0, .width=1, .height=1, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
48 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=4, .cbuf_cpp = {4,4,4,4,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
49 // { .minx=0, .miny=0, .width=64, .height=64, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {2,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
50 { .minx=0, .miny=0, .width=1024, .height=1024, .gmem_page_align=1, .nr_cbufs=0, .cbuf_cpp = {0,0,0,0,0,0,0,0,}, .zsbuf_cpp = {2,0,}},
51 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=0, .cbuf_cpp = {0,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
52 { .minx=0, .miny=0, .width=960, .height=540, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
53 { .minx=0, .miny=0, .width=480, .height=270, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
54 // { .minx=0, .miny=0, .width=240, .height=135, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
55 // { .minx=0, .miny=0, .width=120, .height=67, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
56
57 /* trex: */
58 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
59 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
60 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {2,0,}},
61 { .minx=0, .miny=0, .width=960, .height=540, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {2,0,0,0,0,0,0,0,}, .zsbuf_cpp = {2,0,}},
62 { .minx=0, .miny=0, .width=1024, .height=1024, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {2,0,}},
63 // { .minx=0, .miny=0, .width=64, .height=64, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {2,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
64
65 /* supertuxkart: */
66 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
67 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {2,0,}},
68 { .minx=0, .miny=0, .width=810, .height=810, .gmem_page_align=1, .nr_cbufs=2, .cbuf_cpp = {4,4,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
69 // { .minx=0, .miny=0, .width=405, .height=405, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {2,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
70 { .minx=0, .miny=0, .width=405, .height=405, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {8,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
71 { .minx=0, .miny=0, .width=810, .height=810, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {8,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
72 { .minx=0, .miny=0, .width=810, .height=810, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
73 { .minx=0, .miny=0, .width=810, .height=810, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
74 { .minx=0, .miny=0, .width=960, .height=540, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {2,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
75 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {8,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
76 { .minx=0, .miny=0, .width=960, .height=540, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {8,0,0,0,0,0,0,0,}, .zsbuf_cpp = {0,0,}},
77 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=2, .cbuf_cpp = {4,4,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
78 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {8,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
79 { .minx=0, .miny=0, .width=1920, .height=1080, .gmem_page_align=1, .nr_cbufs=1, .cbuf_cpp = {4,0,0,0,0,0,0,0,}, .zsbuf_cpp = {4,0,}},
80 };
81 /* clang-format on */
82
83 struct gpu_info {
84 const char *name;
85 uint32_t gpu_id;
86 uint8_t gmem_page_align;
87 uint32_t gmemsize_bytes;
88 };
89
90 #define SZ_128K 0x00020000
91 #define SZ_256K 0x00040000
92 #define SZ_512K 0x00080000
93 #define SZ_1M 0x00100000
94
95 /* keep sorted by gpu name: */
96 static const struct gpu_info gpu_infos[] = {
97 {"a306", 307, 4, SZ_128K},
98 {"a405", 405, 4, SZ_256K},
99 {"a530", 530, 4, SZ_1M},
100 {"a618", 618, 1, SZ_512K},
101 {"a630", 630, 1, SZ_1M},
102 {"a650", 630, 1, SZ_1M + SZ_128K},
103 };
104
105 static const struct option opts[] = {
106 {.name = "gpu", .has_arg = 1, NULL, 'g'},
107 {.name = "help", .has_arg = 0, NULL, 'h'},
108 {.name = "verbose", .has_arg = 0, NULL, 'v'},
109 {}};
110
111 static void
usage(void)112 usage(void)
113 {
114 fprintf(stderr, "Usage:\n\n"
115 "\tgmemtool [-hv] [-g GPU]\n\n"
116 "Options:\n"
117 "\t-g, --gpu=GPU - use GMEM size/alignment/etc settings "
118 "for the specified GPU\n"
119 "\t-h, --help - this usage message\n"
120 "\t-v, --verbose - dump more verbose output\n"
121 "\n");
122 fprintf(stderr, "Where GPU is one of:\n");
123 for (int i = 0; i < ARRAY_SIZE(gpu_infos); i++)
124 fprintf(stderr, "\t%s\n", gpu_infos[i].name);
125 exit(2);
126 }
127
128 int
main(int argc,char ** argv)129 main(int argc, char **argv)
130 {
131 const char *gpu_name = "a630";
132 int c;
133
134 while ((c = getopt_long(argc, argv, "g:hv", opts, NULL)) != -1) {
135 switch (c) {
136 case 'g':
137 gpu_name = optarg;
138 break;
139 case 'v':
140 bin_debug = true;
141 break;
142 case 'h':
143 default:
144 usage();
145 }
146 }
147
148 const struct gpu_info *gpu_info = NULL;
149
150 for (int i = 0; i < ARRAY_SIZE(gpu_infos); i++) {
151 if (strcmp(gpu_name, gpu_infos[i].name) == 0) {
152 gpu_info = &gpu_infos[i];
153 break;
154 }
155 }
156
157 if (!gpu_info) {
158 printf("unrecognized gpu name: %s\n", gpu_name);
159 usage();
160 }
161
162 struct fd_dev_id dev_id = {
163 .gpu_id = gpu_info->gpu_id,
164 };
165 /* Setup a fake screen with enough GMEM related configuration
166 * to make gmem_stateobj_init() happy:
167 */
168 struct fd_screen screen = {
169 .dev_id = &dev_id,
170 .gmemsize_bytes = gpu_info->gmemsize_bytes,
171 };
172
173 screen.info = fd_dev_info(&dev_id);
174
175 /* And finally run thru all the GMEM keys: */
176 for (int i = 0; i < ARRAY_SIZE(keys); i++) {
177 struct gmem_key key = keys[i];
178 key.gmem_page_align = gpu_info->gmem_page_align;
179 struct fd_gmem_stateobj *gmem = gmem_stateobj_init(&screen, &key);
180 dump_gmem_state(gmem);
181
182 assert((gmem->bin_w * gmem->nbins_x) >= key.width);
183 assert((gmem->bin_h * gmem->nbins_y) >= key.height);
184 assert(gmem->bin_w < screen.info->tile_max_w);
185 assert(gmem->bin_h < screen.info->tile_max_h);
186
187 ralloc_free(gmem);
188 }
189
190 return 0;
191 }
192