blob: 210aef9d1f98d765cff5041cdb1d70252bc39f94 [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.
Chia-I Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Chia-I Wu00a23b22014-08-20 15:28:08 +080026 */
27
28#ifndef CMD_PRIV_H
29#define CMD_PRIV_H
30
Chia-I Wue24c3292014-08-21 14:05:23 +080031#include "genhw/genhw.h"
Chia-I Wu32710d72014-08-20 16:05:22 +080032#include "dev.h"
33#include "gpu.h"
Chia-I Wu00a23b22014-08-20 15:28:08 +080034#include "cmd.h"
35
Chia-I Wu32710d72014-08-20 16:05:22 +080036#define CMD_ASSERT(cmd, min_gen, max_gen) \
37 INTEL_GPU_ASSERT((cmd)->dev->gpu, (min_gen), (max_gen))
38
Chia-I Wu958d1b72014-08-21 11:28:11 +080039struct intel_cmd_reloc {
Chia-I Wu68f319d2014-09-09 09:43:21 +080040 enum intel_cmd_writer_type which;
Chia-I Wu958d1b72014-08-21 11:28:11 +080041 XGL_UINT pos;
42
43 uint32_t val;
Chia-I Wu9ee38722014-08-25 12:11:36 +080044 struct intel_bo *bo;
Chia-I Wu958d1b72014-08-21 11:28:11 +080045
Chia-I Wu32a22462014-08-26 14:13:46 +080046 uint32_t flags;
Chia-I Wu958d1b72014-08-21 11:28:11 +080047};
48
Chia-I Wu9f039862014-08-20 15:39:56 +080049static inline int cmd_gen(const struct intel_cmd *cmd)
50{
51 return intel_gpu_gen(cmd->dev->gpu);
52}
53
Chia-I Wucdff0592014-08-22 09:27:36 +080054static inline void cmd_reserve_reloc(struct intel_cmd *cmd,
55 XGL_UINT reloc_len)
56{
57 /* fail silently */
58 if (cmd->reloc_used + reloc_len > cmd->reloc_count) {
59 cmd->reloc_used = 0;
60 cmd->result = XGL_ERROR_TOO_MANY_MEMORY_REFERENCES;
61 }
62 assert(cmd->reloc_used + reloc_len <= cmd->reloc_count);
63}
64
Chia-I Wue24c3292014-08-21 14:05:23 +080065void cmd_writer_grow(struct intel_cmd *cmd,
Chia-I Wu3c3edc02014-09-09 10:32:59 +080066 enum intel_cmd_writer_type which,
67 XGL_UINT new_size);
Chia-I Wu00a23b22014-08-20 15:28:08 +080068
Chia-I Wu32710d72014-08-20 16:05:22 +080069/**
Chia-I Wubda55fd2014-08-25 12:46:10 +080070 * Add a reloc at \p pos. No error checking.
Chia-I Wucdff0592014-08-22 09:27:36 +080071 */
72static inline void cmd_writer_add_reloc(struct intel_cmd *cmd,
Chia-I Wu68f319d2014-09-09 09:43:21 +080073 enum intel_cmd_writer_type which,
Chia-I Wubda55fd2014-08-25 12:46:10 +080074 XGL_UINT pos, uint32_t val,
Chia-I Wu9ee38722014-08-25 12:11:36 +080075 struct intel_bo *bo,
Chia-I Wu32a22462014-08-26 14:13:46 +080076 uint32_t flags)
Chia-I Wucdff0592014-08-22 09:27:36 +080077{
78 struct intel_cmd_reloc *reloc = &cmd->relocs[cmd->reloc_used];
79
80 assert(cmd->reloc_used < cmd->reloc_count);
81
Chia-I Wu68f319d2014-09-09 09:43:21 +080082 reloc->which = which;
Chia-I Wubda55fd2014-08-25 12:46:10 +080083 reloc->pos = pos;
Chia-I Wucdff0592014-08-22 09:27:36 +080084 reloc->val = val;
Chia-I Wu9ee38722014-08-25 12:11:36 +080085 reloc->bo = bo;
Chia-I Wu32a22462014-08-26 14:13:46 +080086 reloc->flags = flags;
Chia-I Wucdff0592014-08-22 09:27:36 +080087
88 cmd->reloc_used++;
89}
90
91/**
92 * Reserve \p len DWords in the batch buffer for building a hardware command.
Chia-I Wue24c3292014-08-21 14:05:23 +080093 */
94static inline void cmd_batch_reserve(struct intel_cmd *cmd, XGL_UINT len)
95{
Chia-I Wu68f319d2014-09-09 09:43:21 +080096 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_BATCH];
Chia-I Wue24c3292014-08-21 14:05:23 +080097
98 if (writer->used + len > writer->size)
Chia-I Wu3c3edc02014-09-09 10:32:59 +080099 cmd_writer_grow(cmd, INTEL_CMD_WRITER_BATCH, 0);
Chia-I Wue24c3292014-08-21 14:05:23 +0800100 assert(writer->used + len <= writer->size);
101}
102
103/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800104 * Reserve \p len DWords in the batch buffer and \p reloc_len relocs for
105 * building a hardware command.
106 */
107static inline void cmd_batch_reserve_reloc(struct intel_cmd *cmd,
108 XGL_UINT len, XGL_UINT reloc_len)
109{
110 cmd_reserve_reloc(cmd, reloc_len);
111 cmd_batch_reserve(cmd, len);
112}
113
114/**
115 * Add a DWord to the hardware command being built. No error checking.
Chia-I Wue24c3292014-08-21 14:05:23 +0800116 */
117static inline void cmd_batch_write(struct intel_cmd *cmd, uint32_t val)
118{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800119 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_BATCH];
Chia-I Wue24c3292014-08-21 14:05:23 +0800120
121 assert(writer->used < writer->size);
Chia-I Wu0f50ba82014-09-09 10:25:46 +0800122 ((uint32_t *) writer->ptr)[writer->used++] = val;
Chia-I Wue24c3292014-08-21 14:05:23 +0800123}
124
125/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800126 * Add \p len DWords to the hardware command being built. No error checking.
127 */
128static inline void cmd_batch_write_n(struct intel_cmd *cmd,
129 const uint32_t *vals, XGL_UINT len)
130{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800131 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_BATCH];
Chia-I Wucdff0592014-08-22 09:27:36 +0800132
133 assert(writer->used + len <= writer->size);
134
Chia-I Wu0f50ba82014-09-09 10:25:46 +0800135 memcpy((uint32_t *) writer->ptr + writer->used,
Chia-I Wucdff0592014-08-22 09:27:36 +0800136 vals, sizeof(uint32_t) * len);
137 writer->used += len;
138}
139
140/**
141 * Add a reloc to the hardware command being built. No error checking.
Chia-I Wue24c3292014-08-21 14:05:23 +0800142 */
143static inline void cmd_batch_reloc(struct intel_cmd *cmd,
Chia-I Wu9ee38722014-08-25 12:11:36 +0800144 uint32_t val, struct intel_bo *bo,
Chia-I Wu32a22462014-08-26 14:13:46 +0800145 uint32_t flags)
Chia-I Wue24c3292014-08-21 14:05:23 +0800146{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800147 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_BATCH];
Chia-I Wue24c3292014-08-21 14:05:23 +0800148
Chia-I Wu68f319d2014-09-09 09:43:21 +0800149 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_BATCH,
150 writer->used, val, bo, flags);
Chia-I Wu5e25c272014-08-21 20:19:12 +0800151
Chia-I Wue24c3292014-08-21 14:05:23 +0800152 writer->used++;
153}
154
155/**
Chia-I Wu48c283d2014-08-25 23:13:46 +0800156 * Begin the batch buffer.
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800157 */
158static inline void cmd_batch_begin(struct intel_cmd *cmd)
159{
Chia-I Wu48c283d2014-08-25 23:13:46 +0800160 /* STATE_BASE_ADDRESS */
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800161 const uint8_t cmd_len = 10;
Chia-I Wu426072d2014-08-26 14:31:55 +0800162 const uint32_t dw0 = GEN6_RENDER_CMD(COMMON, STATE_BASE_ADDRESS) |
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800163 (cmd_len - 2);
164
165 CMD_ASSERT(cmd, 6, 7.5);
166
167 cmd_batch_reserve(cmd, cmd_len);
168
169 /* relocs are not added until cmd_batch_end() */
Chia-I Wu68f319d2014-09-09 09:43:21 +0800170 assert(cmd->writers[INTEL_CMD_WRITER_BATCH].used == 0);
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800171
172 cmd_batch_write(cmd, dw0);
173
174 /* start offsets */
175 cmd_batch_write(cmd, 1);
176 cmd_batch_write(cmd, 1);
177 cmd_batch_write(cmd, 1);
178 cmd_batch_write(cmd, 1);
179 cmd_batch_write(cmd, 1);
180 /* end offsets */
181 cmd_batch_write(cmd, 1);
182 cmd_batch_write(cmd, 1 + 0xfffff000);
183 cmd_batch_write(cmd, 1 + 0xfffff000);
184 cmd_batch_write(cmd, 1);
185}
186
187/**
Chia-I Wue24c3292014-08-21 14:05:23 +0800188 * End the batch buffer.
189 */
190static inline void cmd_batch_end(struct intel_cmd *cmd)
191{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800192 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_BATCH];
193 const struct intel_cmd_writer *state =
194 &cmd->writers[INTEL_CMD_WRITER_STATE];
195 const struct intel_cmd_writer *inst =
196 &cmd->writers[INTEL_CMD_WRITER_INSTRUCTION];
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800197
198 cmd_reserve_reloc(cmd, 5);
Chia-I Wu68f319d2014-09-09 09:43:21 +0800199 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_BATCH,
200 2, 1, state->bo, 0);
201 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_BATCH,
202 3, 1, state->bo, 0);
203 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_BATCH,
204 5, 1, inst->bo, 0);
205 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_BATCH,
206 7, 1 + (state->size << 2), state->bo, 0);
207 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_BATCH,
208 9, 1 + (inst->size << 2), inst->bo, 0);
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800209
Chia-I Wu68f319d2014-09-09 09:43:21 +0800210 if (writer->used & 1) {
Chia-I Wue24c3292014-08-21 14:05:23 +0800211 cmd_batch_reserve(cmd, 1);
Chia-I Wu426072d2014-08-26 14:31:55 +0800212 cmd_batch_write(cmd, GEN6_MI_CMD(MI_BATCH_BUFFER_END));
Chia-I Wue24c3292014-08-21 14:05:23 +0800213 } else {
214 cmd_batch_reserve(cmd, 2);
Chia-I Wu426072d2014-08-26 14:31:55 +0800215 cmd_batch_write(cmd, GEN6_MI_CMD(MI_BATCH_BUFFER_END));
216 cmd_batch_write(cmd, GEN6_MI_CMD(MI_NOOP));
Chia-I Wue24c3292014-08-21 14:05:23 +0800217 }
Chia-I Wu343b1372014-08-20 16:39:20 +0800218}
219
Chia-I Wu525c6602014-08-27 10:22:34 +0800220void cmd_batch_flush(struct intel_cmd *cmd, uint32_t pipe_control_dw0);
221
Chia-I Wu759fa2e2014-08-30 18:44:47 +0800222void cmd_batch_depth_count(struct intel_cmd *cmd,
223 struct intel_bo *bo,
224 XGL_GPU_SIZE offset);
225
Chia-I Wue8dbd5d2014-08-31 13:15:58 +0800226void cmd_batch_timestamp(struct intel_cmd *cmd,
227 struct intel_bo *bo,
228 XGL_GPU_SIZE offset);
229
230void cmd_batch_immediate(struct intel_cmd *cmd,
231 struct intel_bo *bo,
232 XGL_GPU_SIZE offset,
233 uint64_t val);
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{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800244 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_STATE];
Chia-I Wu24565ee2014-08-21 20:24:31 +0800245 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)
Chia-I Wu3c3edc02014-09-09 10:32:59 +0800251 cmd_writer_grow(cmd, INTEL_CMD_WRITER_STATE, 0);
Chia-I Wu24565ee2014-08-21 20:24:31 +0800252 assert(aligned + len <= writer->size);
253
254 writer->used = aligned;
255 *pos = aligned;
256
Chia-I Wu0f50ba82014-09-09 10:25:46 +0800257 return &((uint32_t *) writer->ptr)[writer->used];
Chia-I Wu24565ee2014-08-21 20:24:31 +0800258}
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,
Chia-I Wu32a22462014-08-26 14:13:46 +0800281 uint32_t flags)
Chia-I Wubda55fd2014-08-25 12:46:10 +0800282{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800283 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_STATE];
Chia-I Wubda55fd2014-08-25 12:46:10 +0800284
Chia-I Wu68f319d2014-09-09 09:43:21 +0800285 cmd_writer_add_reloc(cmd, INTEL_CMD_WRITER_STATE,
286 writer->used + offset, val, bo, flags);
Chia-I Wubda55fd2014-08-25 12:46:10 +0800287}
288
289/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800290 * Advance the writer position of the state buffer. No error checking.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800291 */
292static inline void cmd_state_advance(struct intel_cmd *cmd, XGL_UINT len)
293{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800294 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_STATE];
Chia-I Wu24565ee2014-08-21 20:24:31 +0800295
296 assert(writer->used + len <= writer->size);
297 writer->used += len;
298}
299
300/**
Chia-I Wucdff0592014-08-22 09:27:36 +0800301 * A convenient function to copy a hardware state of \p len DWords into the
302 * state buffer. The position of the state is returned.
Chia-I Wu24565ee2014-08-21 20:24:31 +0800303 */
304static inline XGL_UINT cmd_state_copy(struct intel_cmd *cmd,
305 const uint32_t *vals, XGL_UINT len,
306 XGL_UINT alignment)
307{
308 uint32_t *dst;
309 XGL_UINT pos;
310
311 dst = cmd_state_reserve(cmd, len, alignment, &pos);
312 memcpy(dst, vals, sizeof(uint32_t) * len);
313 cmd_state_advance(cmd, len);
314
315 return pos;
316}
317
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800318static inline XGL_UINT cmd_kernel_copy(struct intel_cmd *cmd,
319 const void *kernel, XGL_SIZE size)
320{
321 /*
322 * From the Sandy Bridge PRM, volume 4 part 2, page 112:
323 *
324 * "Due to prefetch of the instruction stream, the EUs may attempt to
325 * access up to 8 instructions (128 bytes) beyond the end of the
326 * kernel program - possibly into the next memory page. Although
327 * these instructions will not be executed, software must account for
328 * the prefetch in order to avoid invalid page access faults."
329 */
330 const XGL_UINT prefetch_len = 128 / sizeof(uint32_t);
331 /* kernels are aligned to 64-byte */
332 const XGL_UINT kernel_align = 64 / sizeof(uint32_t);
333 const XGL_UINT kernel_len = ((size + 3) & ~3) / sizeof(uint32_t);
Chia-I Wu68f319d2014-09-09 09:43:21 +0800334 struct intel_cmd_writer *writer =
335 &cmd->writers[INTEL_CMD_WRITER_INSTRUCTION];
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800336 XGL_UINT kernel_pos;
337
338 kernel_pos = u_align(writer->used, kernel_align);
339 if (kernel_pos + kernel_len + prefetch_len > writer->size)
Chia-I Wu3c3edc02014-09-09 10:32:59 +0800340 cmd_writer_grow(cmd, INTEL_CMD_WRITER_INSTRUCTION, 0);
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800341 assert(kernel_pos + kernel_len + prefetch_len <= writer->size);
342
Chia-I Wu0f50ba82014-09-09 10:25:46 +0800343 memcpy(&((uint32_t *) writer->ptr)[kernel_pos], kernel, size);
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800344 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 */