blob: eb9cf76c2930b67d26901a7864999b965d4ac475 [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 Wu00b51a82014-09-09 12:07:37 +080039enum intel_cmd_item_type {
40 /* for state buffer */
41 INTEL_CMD_ITEM_BLOB,
42 INTEL_CMD_ITEM_CLIP_VIEWPORT,
43 INTEL_CMD_ITEM_SF_VIEWPORT,
44 INTEL_CMD_ITEM_SCISSOR_RECT,
45 INTEL_CMD_ITEM_CC_VIEWPORT,
46 INTEL_CMD_ITEM_COLOR_CALC,
47 INTEL_CMD_ITEM_DEPTH_STENCIL,
48 INTEL_CMD_ITEM_BLEND,
49 INTEL_CMD_ITEM_SAMPLER,
50
51 /* for surface buffer */
52 INTEL_CMD_ITEM_SURFACE,
53 INTEL_CMD_ITEM_BINDING_TABLE,
54
55 /* for instruction buffer */
56 INTEL_CMD_ITEM_KERNEL,
57
58 INTEL_CMD_ITEM_COUNT,
59};
60
61struct intel_cmd_item {
62 enum intel_cmd_item_type type;
63 XGL_SIZE offset;
64 XGL_SIZE size;
65};
66
Chia-I Wu958d1b72014-08-21 11:28:11 +080067struct intel_cmd_reloc {
Chia-I Wu68f319d2014-09-09 09:43:21 +080068 enum intel_cmd_writer_type which;
Chia-I Wu72292b72014-09-09 10:48:33 +080069 XGL_SIZE offset;
Chia-I Wu958d1b72014-08-21 11:28:11 +080070
Chia-I Wu9ee38722014-08-25 12:11:36 +080071 struct intel_bo *bo;
Chia-I Wu72292b72014-09-09 10:48:33 +080072 uint32_t bo_offset;
Chia-I Wu958d1b72014-08-21 11:28:11 +080073
Chia-I Wu32a22462014-08-26 14:13:46 +080074 uint32_t flags;
Chia-I Wu958d1b72014-08-21 11:28:11 +080075};
76
Chia-I Wu9f039862014-08-20 15:39:56 +080077static inline int cmd_gen(const struct intel_cmd *cmd)
78{
79 return intel_gpu_gen(cmd->dev->gpu);
80}
81
Chia-I Wucdff0592014-08-22 09:27:36 +080082static inline void cmd_reserve_reloc(struct intel_cmd *cmd,
83 XGL_UINT reloc_len)
84{
85 /* fail silently */
86 if (cmd->reloc_used + reloc_len > cmd->reloc_count) {
87 cmd->reloc_used = 0;
88 cmd->result = XGL_ERROR_TOO_MANY_MEMORY_REFERENCES;
89 }
90 assert(cmd->reloc_used + reloc_len <= cmd->reloc_count);
91}
92
Chia-I Wue24c3292014-08-21 14:05:23 +080093void cmd_writer_grow(struct intel_cmd *cmd,
Chia-I Wu3c3edc02014-09-09 10:32:59 +080094 enum intel_cmd_writer_type which,
Chia-I Wu72292b72014-09-09 10:48:33 +080095 XGL_SIZE new_size);
96
Chia-I Wu00b51a82014-09-09 12:07:37 +080097void cmd_writer_record(struct intel_cmd *cmd,
98 enum intel_cmd_writer_type which,
99 enum intel_cmd_item_type type,
100 XGL_SIZE offset, XGL_SIZE size);
101
Chia-I Wu72292b72014-09-09 10:48:33 +0800102/**
103 * Return an offset to a region that is aligned to \p alignment and has at
104 * least \p size bytes.
105 */
106static inline XGL_SIZE cmd_writer_reserve(struct intel_cmd *cmd,
107 enum intel_cmd_writer_type which,
108 XGL_SIZE alignment, XGL_SIZE size)
109{
110 struct intel_cmd_writer *writer = &cmd->writers[which];
111 XGL_SIZE offset;
112
113 assert(alignment && u_is_pow2(alignment));
114 offset = u_align(writer->used, alignment);
115
116 if (offset + size > writer->size) {
117 cmd_writer_grow(cmd, which, offset + size);
118 /* align again in case of errors */
119 offset = u_align(writer->used, alignment);
120
121 assert(offset + size <= writer->size);
122 }
123
124 return offset;
125}
Chia-I Wu00a23b22014-08-20 15:28:08 +0800126
Chia-I Wu32710d72014-08-20 16:05:22 +0800127/**
Chia-I Wubda55fd2014-08-25 12:46:10 +0800128 * Add a reloc at \p pos. No error checking.
Chia-I Wucdff0592014-08-22 09:27:36 +0800129 */
Chia-I Wu72292b72014-09-09 10:48:33 +0800130static inline void cmd_writer_reloc(struct intel_cmd *cmd,
131 enum intel_cmd_writer_type which,
132 XGL_SIZE offset, struct intel_bo *bo,
133 uint32_t bo_offset, uint32_t flags)
Chia-I Wucdff0592014-08-22 09:27:36 +0800134{
135 struct intel_cmd_reloc *reloc = &cmd->relocs[cmd->reloc_used];
136
137 assert(cmd->reloc_used < cmd->reloc_count);
138
Chia-I Wu68f319d2014-09-09 09:43:21 +0800139 reloc->which = which;
Chia-I Wu72292b72014-09-09 10:48:33 +0800140 reloc->offset = offset;
Chia-I Wu9ee38722014-08-25 12:11:36 +0800141 reloc->bo = bo;
Chia-I Wu72292b72014-09-09 10:48:33 +0800142 reloc->bo_offset = bo_offset;
Chia-I Wu32a22462014-08-26 14:13:46 +0800143 reloc->flags = flags;
Chia-I Wucdff0592014-08-22 09:27:36 +0800144
145 cmd->reloc_used++;
146}
147
148/**
Chia-I Wu72292b72014-09-09 10:48:33 +0800149 * Reserve a region from the state buffer. Both the offset, in bytes, and the
150 * pointer to the reserved region are returned.
151 *
152 * Note that \p alignment is in bytes and \p len is in DWords.
Chia-I Wue24c3292014-08-21 14:05:23 +0800153 */
Chia-I Wu72292b72014-09-09 10:48:33 +0800154static inline uint32_t cmd_state_pointer(struct intel_cmd *cmd,
Chia-I Wu00b51a82014-09-09 12:07:37 +0800155 enum intel_cmd_item_type item,
Chia-I Wu72292b72014-09-09 10:48:33 +0800156 XGL_SIZE alignment, XGL_UINT len,
157 uint32_t **dw)
Chia-I Wue24c3292014-08-21 14:05:23 +0800158{
Chia-I Wu72292b72014-09-09 10:48:33 +0800159 const enum intel_cmd_writer_type which = INTEL_CMD_WRITER_STATE;
160 const XGL_SIZE size = len << 2;
161 const XGL_SIZE offset = cmd_writer_reserve(cmd, which, alignment, size);
162 struct intel_cmd_writer *writer = &cmd->writers[which];
Chia-I Wue24c3292014-08-21 14:05:23 +0800163
Chia-I Wu72292b72014-09-09 10:48:33 +0800164 /* all states are at least aligned to 32-bytes */
165 assert(alignment % 32 == 0);
166
167 *dw = (uint32_t *) ((char *) writer->ptr + offset);
168
169 writer->used = offset + size;
170
Chia-I Wu00b51a82014-09-09 12:07:37 +0800171 if (intel_debug & INTEL_DEBUG_BATCH)
172 cmd_writer_record(cmd, which, item, offset, size);
173
Chia-I Wu72292b72014-09-09 10:48:33 +0800174 return offset;
Chia-I Wue24c3292014-08-21 14:05:23 +0800175}
176
177/**
Chia-I Wu72292b72014-09-09 10:48:33 +0800178 * Write a dynamic state to the state buffer.
Chia-I Wucdff0592014-08-22 09:27:36 +0800179 */
Chia-I Wu72292b72014-09-09 10:48:33 +0800180static inline uint32_t cmd_state_write(struct intel_cmd *cmd,
Chia-I Wu00b51a82014-09-09 12:07:37 +0800181 enum intel_cmd_item_type item,
Chia-I Wu72292b72014-09-09 10:48:33 +0800182 XGL_SIZE alignment, XGL_UINT len,
183 const uint32_t *dw)
Chia-I Wucdff0592014-08-22 09:27:36 +0800184{
Chia-I Wu72292b72014-09-09 10:48:33 +0800185 uint32_t offset, *dst;
186
Chia-I Wu00b51a82014-09-09 12:07:37 +0800187 offset = cmd_state_pointer(cmd, item, alignment, len, &dst);
Chia-I Wu72292b72014-09-09 10:48:33 +0800188 memcpy(dst, dw, len << 2);
189
190 return offset;
Chia-I Wucdff0592014-08-22 09:27:36 +0800191}
192
193/**
Chia-I Wu72292b72014-09-09 10:48:33 +0800194 * Write a surface state to the surface buffer. The offset, in bytes, of the
195 * state is returned.
196 *
197 * Note that \p alignment is in bytes and \p len is in DWords.
Chia-I Wue24c3292014-08-21 14:05:23 +0800198 */
Chia-I Wu72292b72014-09-09 10:48:33 +0800199static inline uint32_t cmd_surface_write(struct intel_cmd *cmd,
Chia-I Wu00b51a82014-09-09 12:07:37 +0800200 enum intel_cmd_item_type item,
Chia-I Wu72292b72014-09-09 10:48:33 +0800201 XGL_SIZE alignment, XGL_UINT len,
202 const uint32_t *dw)
Chia-I Wue24c3292014-08-21 14:05:23 +0800203{
Chia-I Wu00b51a82014-09-09 12:07:37 +0800204 assert(item == INTEL_CMD_ITEM_SURFACE ||
205 item == INTEL_CMD_ITEM_BINDING_TABLE);
206
207 return cmd_state_write(cmd, item, alignment, len, dw);
Chia-I Wue24c3292014-08-21 14:05:23 +0800208}
209
210/**
Chia-I Wu72292b72014-09-09 10:48:33 +0800211 * Add a relocation entry for a DWord of a surface state.
Chia-I Wucdff0592014-08-22 09:27:36 +0800212 */
Chia-I Wu72292b72014-09-09 10:48:33 +0800213static inline void cmd_surface_reloc(struct intel_cmd *cmd,
214 uint32_t offset, XGL_UINT dw_index,
215 struct intel_bo *bo,
216 uint32_t bo_offset, uint32_t reloc_flags)
Chia-I Wucdff0592014-08-22 09:27:36 +0800217{
Chia-I Wu72292b72014-09-09 10:48:33 +0800218 const enum intel_cmd_writer_type which = INTEL_CMD_WRITER_STATE;
Chia-I Wucdff0592014-08-22 09:27:36 +0800219
Chia-I Wu72292b72014-09-09 10:48:33 +0800220 cmd_writer_reloc(cmd, which, offset + (dw_index << 2),
221 bo, bo_offset, reloc_flags);
Chia-I Wucdff0592014-08-22 09:27:36 +0800222}
223
224/**
Chia-I Wu72292b72014-09-09 10:48:33 +0800225 * Write a kernel to the instruction buffer. The offset, in bytes, of the
226 * kernel is returned.
Chia-I Wue24c3292014-08-21 14:05:23 +0800227 */
Chia-I Wu72292b72014-09-09 10:48:33 +0800228static inline uint32_t cmd_instruction_write(struct intel_cmd *cmd,
229 XGL_SIZE size,
230 const void *kernel)
Chia-I Wue24c3292014-08-21 14:05:23 +0800231{
Chia-I Wu72292b72014-09-09 10:48:33 +0800232 const enum intel_cmd_writer_type which = INTEL_CMD_WRITER_INSTRUCTION;
233 /*
234 * From the Sandy Bridge PRM, volume 4 part 2, page 112:
235 *
236 * "Due to prefetch of the instruction stream, the EUs may attempt to
237 * access up to 8 instructions (128 bytes) beyond the end of the
238 * kernel program - possibly into the next memory page. Although
239 * these instructions will not be executed, software must account for
240 * the prefetch in order to avoid invalid page access faults."
241 */
242 const XGL_SIZE reserved_size = size + 128;
243 /* kernels are aligned to 64 bytes */
244 const XGL_SIZE alignment = 64;
245 const XGL_SIZE offset = cmd_writer_reserve(cmd,
246 which, alignment, reserved_size);
247 struct intel_cmd_writer *writer = &cmd->writers[which];
Chia-I Wue24c3292014-08-21 14:05:23 +0800248
Chia-I Wu72292b72014-09-09 10:48:33 +0800249 memcpy((char *) writer->ptr + offset, kernel, size);
Chia-I Wu5e25c272014-08-21 20:19:12 +0800250
Chia-I Wu72292b72014-09-09 10:48:33 +0800251 writer->used = offset + size;
252
Chia-I Wu00b51a82014-09-09 12:07:37 +0800253 if (intel_debug & INTEL_DEBUG_BATCH)
254 cmd_writer_record(cmd, which, INTEL_CMD_ITEM_KERNEL, offset, size);
255
Chia-I Wu72292b72014-09-09 10:48:33 +0800256 return offset;
257}
258
259/**
260 * Reserve a region from the batch buffer. Both the offset, in DWords, and
261 * the pointer to the reserved region are returned.
262 *
263 * Note that \p len is in DWords.
264 */
265static inline XGL_UINT cmd_batch_pointer(struct intel_cmd *cmd,
266 XGL_UINT len, uint32_t **dw)
267{
268 const enum intel_cmd_writer_type which = INTEL_CMD_WRITER_BATCH;
269 /*
270 * We know the batch bo is always aligned. Using 1 here should allow the
271 * compiler to optimize away aligning.
272 */
273 const XGL_SIZE alignment = 1;
274 const XGL_SIZE size = len << 2;
275 const XGL_SIZE offset = cmd_writer_reserve(cmd, which, alignment, size);
276 struct intel_cmd_writer *writer = &cmd->writers[which];
277
278 assert(offset % 4 == 0);
279 *dw = (uint32_t *) ((char *) writer->ptr + offset);
280
281 writer->used = offset + size;
282
283 return offset >> 2;
284}
285
286/**
287 * Write a command to the batch buffer.
288 */
289static inline XGL_UINT cmd_batch_write(struct intel_cmd *cmd,
290 XGL_UINT len, const uint32_t *dw)
291{
292 XGL_UINT pos;
293 uint32_t *dst;
294
295 pos = cmd_batch_pointer(cmd, len, &dst);
296 memcpy(dst, dw, len << 2);
297
298 return pos;
299}
300
301/**
302 * Add a relocation entry for a DWord of a command.
303 */
304static inline void cmd_batch_reloc(struct intel_cmd *cmd, XGL_UINT pos,
305 struct intel_bo *bo,
306 uint32_t bo_offset, uint32_t reloc_flags)
307{
308 const enum intel_cmd_writer_type which = INTEL_CMD_WRITER_BATCH;
309
310 cmd_writer_reloc(cmd, which, pos << 2, bo, bo_offset, reloc_flags);
Chia-I Wue24c3292014-08-21 14:05:23 +0800311}
312
313/**
Chia-I Wu48c283d2014-08-25 23:13:46 +0800314 * Begin the batch buffer.
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800315 */
316static inline void cmd_batch_begin(struct intel_cmd *cmd)
317{
Chia-I Wu48c283d2014-08-25 23:13:46 +0800318 /* STATE_BASE_ADDRESS */
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800319 const uint8_t cmd_len = 10;
Chia-I Wu426072d2014-08-26 14:31:55 +0800320 const uint32_t dw0 = GEN6_RENDER_CMD(COMMON, STATE_BASE_ADDRESS) |
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800321 (cmd_len - 2);
Chia-I Wu72292b72014-09-09 10:48:33 +0800322 XGL_UINT pos;
323 uint32_t *dw;
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800324
325 CMD_ASSERT(cmd, 6, 7.5);
326
Chia-I Wu72292b72014-09-09 10:48:33 +0800327 pos = cmd_batch_pointer(cmd, cmd_len, &dw);
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800328
329 /* relocs are not added until cmd_batch_end() */
Chia-I Wu72292b72014-09-09 10:48:33 +0800330 assert(!pos);
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800331
Chia-I Wu72292b72014-09-09 10:48:33 +0800332 dw[0] = dw0;
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800333 /* start offsets */
Chia-I Wu72292b72014-09-09 10:48:33 +0800334 dw[1] = 1;
335 dw[2] = 1;
336 dw[3] = 1;
337 dw[4] = 1;
338 dw[5] = 1;
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800339 /* end offsets */
Chia-I Wu72292b72014-09-09 10:48:33 +0800340 dw[6] = 1;
341 dw[7] = 1 + 0xfffff000;
342 dw[8] = 1 + 0xfffff000;
343 dw[9] = 1;
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800344}
345
346/**
Chia-I Wue24c3292014-08-21 14:05:23 +0800347 * End the batch buffer.
348 */
349static inline void cmd_batch_end(struct intel_cmd *cmd)
350{
Chia-I Wu68f319d2014-09-09 09:43:21 +0800351 struct intel_cmd_writer *writer = &cmd->writers[INTEL_CMD_WRITER_BATCH];
352 const struct intel_cmd_writer *state =
353 &cmd->writers[INTEL_CMD_WRITER_STATE];
354 const struct intel_cmd_writer *inst =
355 &cmd->writers[INTEL_CMD_WRITER_INSTRUCTION];
Chia-I Wu72292b72014-09-09 10:48:33 +0800356 uint32_t *dw;
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800357
358 cmd_reserve_reloc(cmd, 5);
Chia-I Wu72292b72014-09-09 10:48:33 +0800359 cmd_batch_reloc(cmd, 2, state->bo, 1, 0);
360 cmd_batch_reloc(cmd, 3, state->bo, 1, 0);
361 cmd_batch_reloc(cmd, 5, inst->bo, 1, 0);
362 cmd_batch_reloc(cmd, 7, state->bo, 1 + (state->size << 2), 0);
363 cmd_batch_reloc(cmd, 9, inst->bo, 1 + (inst->size << 2), 0);
Chia-I Wu79dfbb32014-08-25 12:19:02 +0800364
Chia-I Wu72292b72014-09-09 10:48:33 +0800365 if (writer->used & 0x7) {
366 cmd_batch_pointer(cmd, 1, &dw);
367 dw[0] = GEN6_MI_CMD(MI_BATCH_BUFFER_END);
Chia-I Wue24c3292014-08-21 14:05:23 +0800368 } else {
Chia-I Wu72292b72014-09-09 10:48:33 +0800369 cmd_batch_pointer(cmd, 2, &dw);
370 dw[0] = GEN6_MI_CMD(MI_BATCH_BUFFER_END);
371 dw[1] = GEN6_MI_CMD(MI_NOOP);
Chia-I Wue24c3292014-08-21 14:05:23 +0800372 }
Chia-I Wu343b1372014-08-20 16:39:20 +0800373}
374
Chia-I Wu525c6602014-08-27 10:22:34 +0800375void cmd_batch_flush(struct intel_cmd *cmd, uint32_t pipe_control_dw0);
376
Chia-I Wu759fa2e2014-08-30 18:44:47 +0800377void cmd_batch_depth_count(struct intel_cmd *cmd,
378 struct intel_bo *bo,
379 XGL_GPU_SIZE offset);
380
Chia-I Wue8dbd5d2014-08-31 13:15:58 +0800381void cmd_batch_timestamp(struct intel_cmd *cmd,
382 struct intel_bo *bo,
383 XGL_GPU_SIZE offset);
384
385void cmd_batch_immediate(struct intel_cmd *cmd,
386 struct intel_bo *bo,
387 XGL_GPU_SIZE offset,
388 uint64_t val);
Chia-I Wu1cbc0052014-08-25 09:50:12 +0800389
Chia-I Wu00a23b22014-08-20 15:28:08 +0800390#endif /* CMD_PRIV_H */