1040ae8f5c43de577afa16ea05a9a13cbbd2c606
[mesa.git] / src / gallium / drivers / vc4 / vc4_simulator.c
1 /*
2 * Copyright © 2014 Broadcom
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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #ifdef USE_VC4_SIMULATOR
25
26 #include "util/u_memory.h"
27
28 #include "vc4_screen.h"
29 #include "vc4_context.h"
30 #include "kernel/vc4_drv.h"
31 #include "vc4_simulator_validate.h"
32 #include "simpenrose/simpenrose.h"
33
34 #define OVERFLOW_SIZE (32 * 1024 * 1024)
35
36 static struct drm_gem_cma_object *
37 vc4_wrap_bo_with_cma(struct drm_device *dev, struct vc4_bo *bo)
38 {
39 struct vc4_context *vc4 = dev->vc4;
40 struct vc4_screen *screen = vc4->screen;
41 struct drm_gem_cma_object *obj = CALLOC_STRUCT(drm_gem_cma_object);
42 uint32_t size = align(bo->size, 4096);
43
44 obj->bo = bo;
45 obj->base.size = size;
46 obj->vaddr = screen->simulator_mem_base + dev->simulator_mem_next;
47 obj->paddr = simpenrose_hw_addr(obj->vaddr);
48
49 dev->simulator_mem_next += size;
50 dev->simulator_mem_next = align(dev->simulator_mem_next, 4096);
51 assert(dev->simulator_mem_next <= screen->simulator_mem_size);
52
53 return obj;
54 }
55
56 struct drm_gem_cma_object *
57 drm_gem_cma_create(struct drm_device *dev, size_t size)
58 {
59 struct vc4_context *vc4 = dev->vc4;
60 struct vc4_screen *screen = vc4->screen;
61
62 struct vc4_bo *bo = vc4_bo_alloc(screen, size, "simulator validate");
63 return vc4_wrap_bo_with_cma(dev, bo);
64 }
65
66 static int
67 vc4_simulator_pin_bos(struct drm_device *dev, struct exec_info *exec)
68 {
69 struct drm_vc4_submit_cl *args = exec->args;
70 struct vc4_context *vc4 = dev->vc4;
71 struct vc4_bo **bos = vc4->bo_pointers.base;
72
73 exec->bo_count = args->bo_handle_count;
74 exec->bo = calloc(exec->bo_count, sizeof(struct vc4_bo_exec_state));
75 for (int i = 0; i < exec->bo_count; i++) {
76 struct vc4_bo *bo = bos[i];
77 struct drm_gem_cma_object *obj = vc4_wrap_bo_with_cma(dev, bo);
78
79 #if 0
80 fprintf(stderr, "bo hindex %d: %s\n", i, bo->name);
81 #endif
82
83 vc4_bo_map(bo);
84 memcpy(obj->vaddr, bo->map, bo->size);
85
86 exec->bo[i].bo = obj;
87 }
88 return 0;
89 }
90
91 static int
92 vc4_simulator_unpin_bos(struct exec_info *exec)
93 {
94 for (int i = 0; i < exec->bo_count; i++) {
95 struct drm_gem_cma_object *obj = exec->bo[i].bo;
96 struct vc4_bo *bo = obj->bo;
97
98 memcpy(bo->map, obj->vaddr, bo->size);
99
100 free(obj);
101 }
102
103 free(exec->bo);
104
105 return 0;
106 }
107
108 int
109 vc4_simulator_flush(struct vc4_context *vc4, struct drm_vc4_submit_cl *args)
110 {
111 struct vc4_screen *screen = vc4->screen;
112 struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
113 struct vc4_resource *ctex = csurf ? vc4_resource(csurf->base.texture) : NULL;
114 uint32_t winsys_stride = ctex ? ctex->bo->simulator_winsys_stride : 0;
115 uint32_t sim_stride = ctex ? ctex->slices[0].stride : 0;
116 uint32_t row_len = MIN2(sim_stride, winsys_stride);
117 struct exec_info exec;
118 struct drm_device local_dev = {
119 .vc4 = vc4,
120 .simulator_mem_next = OVERFLOW_SIZE,
121 };
122 struct drm_device *dev = &local_dev;
123 int ret;
124
125 memset(&exec, 0, sizeof(exec));
126
127 if (ctex && ctex->bo->simulator_winsys_map) {
128 #if 0
129 fprintf(stderr, "%dx%d %d %d %d\n",
130 ctex->base.b.width0, ctex->base.b.height0,
131 winsys_stride,
132 sim_stride,
133 ctex->bo->size);
134 #endif
135
136 for (int y = 0; y < ctex->base.b.height0; y++) {
137 memcpy(ctex->bo->map + y * sim_stride,
138 ctex->bo->simulator_winsys_map + y * winsys_stride,
139 row_len);
140 }
141 }
142
143 exec.args = args;
144
145 ret = vc4_simulator_pin_bos(dev, &exec);
146 if (ret)
147 return ret;
148
149 ret = vc4_cl_validate(dev, &exec);
150 if (ret)
151 return ret;
152
153 int bfc = simpenrose_do_binning(exec.ct0ca, exec.ct0ea);
154 if (bfc != 1) {
155 fprintf(stderr, "Binning returned %d flushes, should be 1.\n",
156 bfc);
157 fprintf(stderr, "Relocated binning command list:\n");
158 vc4_dump_cl(screen->simulator_mem_base + exec.ct0ca,
159 exec.ct0ea - exec.ct0ca, false);
160 abort();
161 }
162 int rfc = simpenrose_do_rendering(exec.ct1ca, exec.ct1ea);
163 if (rfc != 1) {
164 fprintf(stderr, "Rendering returned %d frames, should be 1.\n",
165 rfc);
166 fprintf(stderr, "Relocated render command list:\n");
167 vc4_dump_cl(screen->simulator_mem_base + exec.ct1ca,
168 exec.ct1ea - exec.ct1ca, true);
169 abort();
170 }
171
172 ret = vc4_simulator_unpin_bos(&exec);
173 if (ret)
174 return ret;
175
176 free(exec.exec_bo);
177
178 if (ctex && ctex->bo->simulator_winsys_map) {
179 for (int y = 0; y < ctex->base.b.height0; y++) {
180 memcpy(ctex->bo->simulator_winsys_map + y * winsys_stride,
181 ctex->bo->map + y * sim_stride,
182 row_len);
183 }
184 }
185
186 return 0;
187 }
188
189 void
190 vc4_simulator_init(struct vc4_screen *screen)
191 {
192 screen->simulator_mem_size = 256 * 1024 * 1024;
193 screen->simulator_mem_base = malloc(screen->simulator_mem_size);
194
195 /* We supply our own memory so that we can have more aperture
196 * available (256MB instead of simpenrose's default 64MB).
197 */
198 simpenrose_init_hardware_supply_mem(screen->simulator_mem_base,
199 screen->simulator_mem_size);
200
201 /* Carve out low memory for tile allocation overflow. The kernel
202 * should be automatically handling overflow memory setup on real
203 * hardware, but for simulation we just get one shot to set up enough
204 * overflow memory before execution. This overflow mem will be used
205 * up over the whole lifetime of simpenrose (not reused on each
206 * flush), so it had better be big.
207 */
208 simpenrose_supply_overflow_mem(0, OVERFLOW_SIZE);
209 }
210
211 #endif /* USE_VC4_SIMULATOR */