blob: 1ea8378d1bfb9c84eb5bb1311b238dc7836d310d [file] [log] [blame]
Chia-I Wu00a23b22014-08-20 15:28:08 +08001/*
2 * XGL
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef CMD_PRIV_H
26#define CMD_PRIV_H
27
Chia-I Wue24c3292014-08-21 14:05:23 +080028#include "genhw/genhw.h"
Chia-I Wu32710d72014-08-20 16:05:22 +080029#include "dev.h"
30#include "gpu.h"
Chia-I Wu00a23b22014-08-20 15:28:08 +080031#include "cmd.h"
32
Chia-I Wu32710d72014-08-20 16:05:22 +080033#define CMD_ASSERT(cmd, min_gen, max_gen) \
34 INTEL_GPU_ASSERT((cmd)->dev->gpu, (min_gen), (max_gen))
35
Chia-I Wu958d1b72014-08-21 11:28:11 +080036struct intel_cmd_reloc {
Chia-I Wue24c3292014-08-21 14:05:23 +080037 struct intel_cmd_writer *writer;
Chia-I Wu958d1b72014-08-21 11:28:11 +080038 XGL_UINT pos;
39
40 uint32_t val;
Chia-I Wu9ee38722014-08-25 12:11:36 +080041 struct intel_bo *bo;
Chia-I Wu958d1b72014-08-21 11:28:11 +080042
43 /*
44 * With application state tracking promised by XGL, we should be able to
45 * set
46 *
47 * I915_EXEC_NO_RELOC
48 * I915_EXEC_HANDLE_LUT
49 * I915_EXEC_IS_PINNED
50 *
51 * once we figure them out.
52 */
53 uint16_t read_domains;
54 uint16_t write_domain;
55};
56
Chia-I Wu9f039862014-08-20 15:39:56 +080057static inline int cmd_gen(const struct intel_cmd *cmd)
58{
59 return intel_gpu_gen(cmd->dev->gpu);
60}
61
Chia-I Wucdff0592014-08-22 09:27:36 +080062static inline void cmd_reserve_reloc(struct intel_cmd *cmd,
63 XGL_UINT reloc_len)
64{
65 /* fail silently */
66 if (cmd->reloc_used + reloc_len > cmd->reloc_count) {
67 cmd->reloc_used = 0;
68 cmd->result = XGL_ERROR_TOO_MANY_MEMORY_REFERENCES;
69 }
70 assert(cmd->reloc_used + reloc_len <= cmd->reloc_count);
71}
72
Chia-I Wue24c3292014-08-21 14:05:23 +080073void cmd_writer_grow(struct intel_cmd *cmd,
74 struct intel_cmd_writer *writer);
Chia-I Wu00a23b22014-08-20 15:28:08 +080075
Chia-I Wu32710d72014-08-20 16:05:22 +080076/**
Chia-I Wubda55fd2014-08-25 12:46:10 +080077 * Add a reloc at \p pos. No error checking.
Chia-I Wucdff0592014-08-22 09:27:36 +080078 */
79static inline void cmd_writer_add_reloc(struct intel_cmd *cmd,
80 struct intel_cmd_writer *writer,
Chia-I Wubda55fd2014-08-25 12:46:10 +080081 XGL_UINT pos, uint32_t val,
Chia-I Wu9ee38722014-08-25 12:11:36 +080082 struct intel_bo *bo,
Chia-I Wucdff0592014-08-22 09:27:36 +080083 uint16_t read_domains,
84 uint16_t write_domain)
85{
86 struct intel_cmd_reloc *reloc = &cmd->relocs[cmd->reloc_used];
87
88 assert(cmd->reloc_used < cmd->reloc_count);
89
90 reloc->writer = writer;
Chia-I Wubda55fd2014-08-25 12:46:10 +080091 reloc->pos = pos;
Chia-I Wucdff0592014-08-22 09:27:36 +080092 reloc->val = val;
Chia-I Wu9ee38722014-08-25 12:11:36 +080093 reloc->bo = bo;
Chia-I Wucdff0592014-08-22 09:27:36 +080094 reloc->read_domains = read_domains;
95 reloc->write_domain = write_domain;
96
97 cmd->reloc_used++;
98}
99
100/**
101 * Reserve \p len DWords in the batch buffer for building a hardware command.
Chia-I Wue24c3292014-08-21 14:05:23 +0800102 */
103static inline void cmd_batch_reserve(struct intel_cmd *cmd, XGL_UINT len)
104{
105 struct intel_cmd_writer *writer = &cmd->batch;
106
107 if (writer->used + len > writer->size)
108 cmd_writer_grow(cmd, writer);
109 assert(writer->used + len <= writer->size);
110}
111
112/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800113 * Reserve \p len DWords in the batch buffer and \p reloc_len relocs for
114 * building a hardware command.
115 */
116static inline void cmd_batch_reserve_reloc(struct intel_cmd *cmd,
117 XGL_UINT len, XGL_UINT reloc_len)
118{
119 cmd_reserve_reloc(cmd, reloc_len);
120 cmd_batch_reserve(cmd, len);
121}
122
123/**
124 * Add a DWord to the hardware command being built. No error checking.
Chia-I Wue24c3292014-08-21 14:05:23 +0800125 */
126static inline void cmd_batch_write(struct intel_cmd *cmd, uint32_t val)
127{
128 struct intel_cmd_writer *writer = &cmd->batch;
129
130 assert(writer->used < writer->size);
131 ((uint32_t *) writer->ptr_opaque)[writer->used++] = val;
132}
133
134/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800135 * Add \p len DWords to the hardware command being built. No error checking.
136 */
137static inline void cmd_batch_write_n(struct intel_cmd *cmd,
138 const uint32_t *vals, XGL_UINT len)
139{
140 struct intel_cmd_writer *writer = &cmd->batch;
141
142 assert(writer->used + len <= writer->size);
143
144 memcpy((uint32_t *) writer->ptr_opaque + writer->used,
145 vals, sizeof(uint32_t) * len);
146 writer->used += len;
147}
148
149/**
150 * Add a reloc to the hardware command being built. No error checking.
Chia-I Wue24c3292014-08-21 14:05:23 +0800151 */
152static inline void cmd_batch_reloc(struct intel_cmd *cmd,
Chia-I Wu9ee38722014-08-25 12:11:36 +0800153 uint32_t val, struct intel_bo *bo,
Chia-I Wue24c3292014-08-21 14:05:23 +0800154 uint16_t read_domains,
155 uint16_t write_domain)
156{
157 struct intel_cmd_writer *writer = &cmd->batch;
158
Chia-I Wubda55fd2014-08-25 12:46:10 +0800159 cmd_writer_add_reloc(cmd, writer, writer->used, val,
Chia-I Wu9ee38722014-08-25 12:11:36 +0800160 bo, read_domains, write_domain);
Chia-I Wu5e25c272014-08-21 20:19:12 +0800161
Chia-I Wue24c3292014-08-21 14:05:23 +0800162 writer->used++;
163}
164
165/**
Chia-I Wu48c283d2014-08-25 23:13:46 +0800166 * Begin the batch buffer.
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800167 */
168static inline void cmd_batch_begin(struct intel_cmd *cmd)
169{
Chia-I Wu48c283d2014-08-25 23:13:46 +0800170 /* STATE_BASE_ADDRESS */
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800171 const uint8_t cmd_len = 10;
172 const uint32_t dw0 = GEN_RENDER_CMD(COMMON, GEN6, STATE_BASE_ADDRESS) |
173 (cmd_len - 2);
174
Chia-I Wu48c283d2014-08-25 23:13:46 +0800175 /*
176 * assume all workarounds have been emitted for we do not need them for a
177 * fresh batch buffer
178 */
179 cmd->bind.wa_flags = 0xffffffff;
180
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800181 CMD_ASSERT(cmd, 6, 7.5);
182
183 cmd_batch_reserve(cmd, cmd_len);
184
185 /* relocs are not added until cmd_batch_end() */
186 assert(cmd->batch.used == 0);
187
188 cmd_batch_write(cmd, dw0);
189
190 /* start offsets */
191 cmd_batch_write(cmd, 1);
192 cmd_batch_write(cmd, 1);
193 cmd_batch_write(cmd, 1);
194 cmd_batch_write(cmd, 1);
195 cmd_batch_write(cmd, 1);
196 /* end offsets */
197 cmd_batch_write(cmd, 1);
198 cmd_batch_write(cmd, 1 + 0xfffff000);
199 cmd_batch_write(cmd, 1 + 0xfffff000);
200 cmd_batch_write(cmd, 1);
201}
202
203/**
Chia-I Wue24c3292014-08-21 14:05:23 +0800204 * End the batch buffer.
205 */
206static inline void cmd_batch_end(struct intel_cmd *cmd)
207{
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800208 struct intel_cmd_writer *writer = &cmd->batch;
209 const struct intel_cmd_writer *state = &cmd->state;
210 const struct intel_cmd_writer *kernel = &cmd->kernel;
211
212 cmd_reserve_reloc(cmd, 5);
213 cmd_writer_add_reloc(cmd, writer, 2, 1,
214 state->bo, INTEL_DOMAIN_SAMPLER, 0);
215 cmd_writer_add_reloc(cmd, writer, 3, 1,
216 state->bo, INTEL_DOMAIN_RENDER | INTEL_DOMAIN_INSTRUCTION, 0);
217 cmd_writer_add_reloc(cmd, writer, 5, 1,
218 kernel->bo, INTEL_DOMAIN_INSTRUCTION, 0);
219 cmd_writer_add_reloc(cmd, writer, 7, 1 + (state->size << 2),
220 state->bo, INTEL_DOMAIN_RENDER | INTEL_DOMAIN_INSTRUCTION, 0);
221 cmd_writer_add_reloc(cmd, writer, 9, 1 + (kernel->size << 2),
222 kernel->bo, INTEL_DOMAIN_INSTRUCTION, 0);
223
Chia-I Wue24c3292014-08-21 14:05:23 +0800224 if (cmd->batch.used & 1) {
225 cmd_batch_reserve(cmd, 1);
226 cmd_batch_write(cmd, GEN_MI_CMD(MI_BATCH_BUFFER_END));
227 } else {
228 cmd_batch_reserve(cmd, 2);
229 cmd_batch_write(cmd, GEN_MI_CMD(MI_BATCH_BUFFER_END));
230 cmd_batch_write(cmd, GEN_MI_CMD(MI_NOOP));
231 }
Chia-I Wu343b1372014-08-20 16:39:20 +0800232}
233
Chia-I Wu24565ee2014-08-21 20:24:31 +0800234/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800235 * Reserve \p len DWords in the state buffer for building a hardware state.
236 * The current writer position is aligned to \p alignment first. Both the
237 * pointer to the reserved region and the aligned position are returned.
238 *
239 * Note that the returned pointer is only valid until the next reserve call.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800240 */
241static inline uint32_t *cmd_state_reserve(struct intel_cmd *cmd, XGL_UINT len,
242 XGL_UINT alignment, XGL_UINT *pos)
243{
244 struct intel_cmd_writer *writer = &cmd->state;
245 XGL_UINT aligned;
246
247 assert(alignment && u_is_pow2(alignment));
248 aligned = u_align(writer->used, alignment);
249
250 if (aligned + len > writer->size)
251 cmd_writer_grow(cmd, writer);
252 assert(aligned + len <= writer->size);
253
254 writer->used = aligned;
255 *pos = aligned;
256
257 return &((uint32_t *) writer->ptr_opaque)[writer->used];
258}
259
260/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800261 * Similar to \p cmd_state_reserve, except that \p reloc_len relocs are also
262 * reserved.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800263 */
Chia-I Wucdff0592014-08-22 09:27:36 +0800264static inline uint32_t *cmd_state_reserve_reloc(struct intel_cmd *cmd,
265 XGL_UINT len,
266 XGL_UINT reloc_len,
267 XGL_UINT alignment,
268 XGL_UINT *pos)
Chia-I Wu24565ee2014-08-21 20:24:31 +0800269{
Chia-I Wucdff0592014-08-22 09:27:36 +0800270 cmd_reserve_reloc(cmd, reloc_len);
271 return cmd_state_reserve(cmd, len, alignment, pos);
Chia-I Wu24565ee2014-08-21 20:24:31 +0800272}
273
274/**
Chia-I Wubda55fd2014-08-25 12:46:10 +0800275 * Add a reloc at \p offset, relative to the current writer position. No
276 * error checking.
277 */
278static inline void cmd_state_reloc(struct intel_cmd *cmd,
279 XGL_INT offset, uint32_t val,
280 struct intel_bo *bo,
281 uint16_t read_domains,
282 uint16_t write_domain)
283{
284 struct intel_cmd_writer *writer = &cmd->state;
285
286 cmd_writer_add_reloc(cmd, writer, writer->used + offset, val,
287 bo, read_domains, write_domain);
288}
289
290/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800291 * Advance the writer position of the state buffer. No error checking.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800292 */
293static inline void cmd_state_advance(struct intel_cmd *cmd, XGL_UINT len)
294{
295 struct intel_cmd_writer *writer = &cmd->state;
296
297 assert(writer->used + len <= writer->size);
298 writer->used += len;
299}
300
301/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800302 * A convenient function to copy a hardware state of \p len DWords into the
303 * state buffer. The position of the state is returned.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800304 */
305static inline XGL_UINT cmd_state_copy(struct intel_cmd *cmd,
306 const uint32_t *vals, XGL_UINT len,
307 XGL_UINT alignment)
308{
309 uint32_t *dst;
310 XGL_UINT pos;
311
312 dst = cmd_state_reserve(cmd, len, alignment, &pos);
313 memcpy(dst, vals, sizeof(uint32_t) * len);
314 cmd_state_advance(cmd, len);
315
316 return pos;
317}
318
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800319static inline XGL_UINT cmd_kernel_copy(struct intel_cmd *cmd,
320 const void *kernel, XGL_SIZE size)
321{
322 /*
323 * From the Sandy Bridge PRM, volume 4 part 2, page 112:
324 *
325 * "Due to prefetch of the instruction stream, the EUs may attempt to
326 * access up to 8 instructions (128 bytes) beyond the end of the
327 * kernel program - possibly into the next memory page. Although
328 * these instructions will not be executed, software must account for
329 * the prefetch in order to avoid invalid page access faults."
330 */
331 const XGL_UINT prefetch_len = 128 / sizeof(uint32_t);
332 /* kernels are aligned to 64-byte */
333 const XGL_UINT kernel_align = 64 / sizeof(uint32_t);
334 const XGL_UINT kernel_len = ((size + 3) & ~3) / sizeof(uint32_t);
335 struct intel_cmd_writer *writer = &cmd->kernel;
336 XGL_UINT kernel_pos;
337
338 kernel_pos = u_align(writer->used, kernel_align);
339 if (kernel_pos + kernel_len + prefetch_len > writer->size)
340 cmd_writer_grow(cmd, writer);
341 assert(kernel_pos + kernel_len + prefetch_len <= writer->size);
342
343 memcpy(&((uint32_t *) writer->ptr_opaque)[kernel_pos], kernel, size);
344 writer->used = kernel_pos + kernel_len;
345
346 return kernel_pos;
347}
348
Chia-I Wu00a23b22014-08-20 15:28:08 +0800349#endif /* CMD_PRIV_H */