blob: 55b621a58c978417355dfcce1c48b016264a0ff6 [file] [log] [blame]
Chia-I Wue09b5362014-08-07 09:25:14 +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 Wue09b5362014-08-07 09:25:14 +080026 */
27
Chia-I Wu3ad3c542014-08-25 11:09:17 +080028#include "genhw/genhw.h"
Chia-I Wue09b5362014-08-07 09:25:14 +080029#include "kmd/winsys.h"
Chia-I Wu34f45182014-08-19 14:02:59 +080030#include "cmd.h"
Chia-I Wue09b5362014-08-07 09:25:14 +080031#include "dev.h"
Chia-I Wuc5438c22014-08-19 14:03:06 +080032#include "fence.h"
Chia-I Wue09b5362014-08-07 09:25:14 +080033#include "queue.h"
34
Chia-I Wu465fe212015-02-11 11:27:06 -070035static void queue_submit_hang(struct intel_queue *queue,
36 struct intel_cmd *cmd,
37 uint32_t active_lost,
38 uint32_t pending_lost)
39{
40 intel_cmd_decode(cmd, true);
41
42 intel_dev_log(queue->dev, XGL_DBG_MSG_ERROR,
43 XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE, 0, 0,
44 "GPU hanged with %d/%d active/pending command buffers lost",
45 active_lost, pending_lost);
46}
47
Chia-I Wu94d2fba2014-08-25 11:38:08 +080048static XGL_RESULT queue_submit_bo(struct intel_queue *queue,
49 struct intel_bo *bo,
50 XGL_GPU_SIZE used)
51{
52 struct intel_winsys *winsys = queue->dev->winsys;
53 int err;
54
Chia-I Wu94d2fba2014-08-25 11:38:08 +080055 if (intel_debug & INTEL_DEBUG_NOHW)
56 err = 0;
57 else
58 err = intel_winsys_submit_bo(winsys, queue->ring, bo, used, 0);
59
60 return (err) ? XGL_ERROR_UNKNOWN : XGL_SUCCESS;
61}
62
Chia-I Wuec841722014-08-25 22:36:01 +080063static struct intel_bo *queue_create_bo(struct intel_queue *queue,
64 XGL_GPU_SIZE size,
65 const void *cmd,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060066 size_t cmd_len)
Chia-I Wu3ad3c542014-08-25 11:09:17 +080067{
Chia-I Wuec841722014-08-25 22:36:01 +080068 struct intel_bo *bo;
69 void *ptr;
70
71 bo = intel_winsys_alloc_buffer(queue->dev->winsys,
Chia-I Wu32a22462014-08-26 14:13:46 +080072 "queue bo", size, true);
Chia-I Wuec841722014-08-25 22:36:01 +080073 if (!bo)
74 return NULL;
75
76 if (!cmd_len)
77 return bo;
78
79 ptr = intel_bo_map(bo, true);
80 if (!ptr) {
81 intel_bo_unreference(bo);
82 return NULL;
83 }
84
85 memcpy(ptr, cmd, cmd_len);
86 intel_bo_unmap(bo);
87
88 return bo;
89}
90
91static XGL_RESULT queue_select_pipeline(struct intel_queue *queue,
92 int pipeline_select)
93{
94 uint32_t pipeline_select_cmd[] = {
Chia-I Wu426072d2014-08-26 14:31:55 +080095 GEN6_RENDER_CMD(SINGLE_DW, PIPELINE_SELECT),
96 GEN6_MI_CMD(MI_BATCH_BUFFER_END),
Chia-I Wuec841722014-08-25 22:36:01 +080097 };
98 struct intel_bo *bo;
99 XGL_RESULT ret;
100
101 if (queue->ring != INTEL_RING_RENDER ||
102 queue->last_pipeline_select == pipeline_select)
103 return XGL_SUCCESS;
104
105 switch (pipeline_select) {
106 case GEN6_PIPELINE_SELECT_DW0_SELECT_3D:
107 bo = queue->select_graphics_bo;
108 break;
109 case GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA:
110 bo = queue->select_compute_bo;
111 break;
112 default:
113 return XGL_ERROR_INVALID_VALUE;
114 break;
115 }
116
117 if (!bo) {
118 pipeline_select_cmd[0] |= pipeline_select;
119 bo = queue_create_bo(queue, sizeof(pipeline_select_cmd),
120 pipeline_select_cmd, sizeof(pipeline_select_cmd));
121 if (!bo)
122 return XGL_ERROR_OUT_OF_GPU_MEMORY;
123
124 switch (pipeline_select) {
125 case GEN6_PIPELINE_SELECT_DW0_SELECT_3D:
126 queue->select_graphics_bo = bo;
127 break;
128 case GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA:
129 queue->select_compute_bo = bo;
130 break;
131 default:
132 break;
133 }
134 }
135
136 ret = queue_submit_bo(queue, bo, sizeof(pipeline_select_cmd));
137 if (ret == XGL_SUCCESS)
138 queue->last_pipeline_select = pipeline_select;
139
140 return ret;
141}
142
143static XGL_RESULT queue_init_hw_and_atomic_bo(struct intel_queue *queue)
144{
145 const uint32_t ctx_init_cmd[] = {
Chia-I Wu63883292014-08-25 13:50:26 +0800146 /* STATE_SIP */
Chia-I Wu426072d2014-08-26 14:31:55 +0800147 GEN6_RENDER_CMD(COMMON, STATE_SIP),
Chia-I Wu63883292014-08-25 13:50:26 +0800148 0,
149 /* PIPELINE_SELECT */
Chia-I Wu426072d2014-08-26 14:31:55 +0800150 GEN6_RENDER_CMD(SINGLE_DW, PIPELINE_SELECT) |
Chia-I Wu63883292014-08-25 13:50:26 +0800151 GEN6_PIPELINE_SELECT_DW0_SELECT_3D,
152 /* 3DSTATE_VF_STATISTICS */
Chia-I Wu426072d2014-08-26 14:31:55 +0800153 GEN6_RENDER_CMD(SINGLE_DW, 3DSTATE_VF_STATISTICS),
Chia-I Wu63883292014-08-25 13:50:26 +0800154 /* end */
Chia-I Wu426072d2014-08-26 14:31:55 +0800155 GEN6_MI_CMD(MI_BATCH_BUFFER_END),
156 GEN6_MI_CMD(MI_NOOP),
Chia-I Wu63883292014-08-25 13:50:26 +0800157 };
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800158 struct intel_bo *bo;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800159 XGL_RESULT ret;
160
Chia-I Wuec841722014-08-25 22:36:01 +0800161 if (queue->ring != INTEL_RING_RENDER) {
162 queue->last_pipeline_select = -1;
163 queue->atomic_bo = queue_create_bo(queue,
164 sizeof(uint32_t) * INTEL_QUEUE_ATOMIC_COUNTER_COUNT,
165 NULL, 0);
166 return (queue->atomic_bo) ? XGL_SUCCESS : XGL_ERROR_OUT_OF_GPU_MEMORY;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800167 }
168
Chia-I Wuec841722014-08-25 22:36:01 +0800169 bo = queue_create_bo(queue,
170 sizeof(uint32_t) * INTEL_QUEUE_ATOMIC_COUNTER_COUNT,
171 ctx_init_cmd, sizeof(ctx_init_cmd));
172 if (!bo)
173 return XGL_ERROR_OUT_OF_GPU_MEMORY;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800174
Chia-I Wuec841722014-08-25 22:36:01 +0800175 ret = queue_submit_bo(queue, bo, sizeof(ctx_init_cmd));
176 if (ret != XGL_SUCCESS) {
177 intel_bo_unreference(bo);
178 return ret;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800179 }
180
Chia-I Wuec841722014-08-25 22:36:01 +0800181 queue->last_pipeline_select = GEN6_PIPELINE_SELECT_DW0_SELECT_3D;
182 /* reuse */
183 queue->atomic_bo = bo;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800184
Chia-I Wuec841722014-08-25 22:36:01 +0800185 return XGL_SUCCESS;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800186}
187
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800188XGL_RESULT intel_queue_create(struct intel_dev *dev,
Chia-I Wucdcff732014-08-19 14:44:15 +0800189 enum intel_gpu_engine_type engine,
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800190 struct intel_queue **queue_ret)
Chia-I Wue09b5362014-08-07 09:25:14 +0800191{
192 struct intel_queue *queue;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800193 enum intel_ring_type ring;
194
Chia-I Wucdcff732014-08-19 14:44:15 +0800195 switch (engine) {
196 case INTEL_GPU_ENGINE_3D:
Chia-I Wuc5438c22014-08-19 14:03:06 +0800197 ring = INTEL_RING_RENDER;
198 break;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800199 default:
200 return XGL_ERROR_INVALID_VALUE;
201 break;
202 }
Chia-I Wue09b5362014-08-07 09:25:14 +0800203
Courtney Goeltzenleuchterfb4fb532014-08-14 09:35:21 -0600204 queue = (struct intel_queue *) intel_base_create(dev, sizeof(*queue),
Chia-I Wubbf2c932014-08-07 12:20:08 +0800205 dev->base.dbg, XGL_DBG_OBJECT_QUEUE, NULL, 0);
Chia-I Wue09b5362014-08-07 09:25:14 +0800206 if (!queue)
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800207 return XGL_ERROR_OUT_OF_MEMORY;
Chia-I Wue09b5362014-08-07 09:25:14 +0800208
Chia-I Wue09b5362014-08-07 09:25:14 +0800209 queue->dev = dev;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800210 queue->ring = ring;
Chia-I Wue09b5362014-08-07 09:25:14 +0800211
Chia-I Wuec841722014-08-25 22:36:01 +0800212 if (queue_init_hw_and_atomic_bo(queue) != XGL_SUCCESS) {
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800213 intel_queue_destroy(queue);
Chia-I Wu63883292014-08-25 13:50:26 +0800214 return XGL_ERROR_INITIALIZATION_FAILED;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800215 }
216
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800217 *queue_ret = queue;
218
219 return XGL_SUCCESS;
Chia-I Wue09b5362014-08-07 09:25:14 +0800220}
221
222void intel_queue_destroy(struct intel_queue *queue)
223{
Chia-I Wu63883292014-08-25 13:50:26 +0800224 if (queue->atomic_bo)
225 intel_bo_unreference(queue->atomic_bo);
226 if (queue->select_graphics_bo)
227 intel_bo_unreference(queue->select_graphics_bo);
228 if (queue->select_compute_bo)
229 intel_bo_unreference(queue->select_compute_bo);
Chia-I Wubbf2c932014-08-07 12:20:08 +0800230 intel_base_destroy(&queue->base);
Chia-I Wue09b5362014-08-07 09:25:14 +0800231}
232
233XGL_RESULT intel_queue_wait(struct intel_queue *queue, int64_t timeout)
234{
Chia-I Wue24c3292014-08-21 14:05:23 +0800235 struct intel_bo *bo = (queue->last_submitted_cmd) ?
236 intel_cmd_get_batch(queue->last_submitted_cmd, NULL) : NULL;
Chia-I Wue09b5362014-08-07 09:25:14 +0800237
Chia-I Wue24c3292014-08-21 14:05:23 +0800238 return (!bo || intel_bo_wait(bo, timeout) == 0) ?
Chia-I Wue09b5362014-08-07 09:25:14 +0800239 XGL_SUCCESS : XGL_ERROR_UNKNOWN;
240}
241
Chia-I Wu96177272015-01-03 15:27:41 +0800242ICD_EXPORT XGL_RESULT XGLAPI xglQueueSetGlobalMemReferences(
Chia-I Wue09b5362014-08-07 09:25:14 +0800243 XGL_QUEUE queue,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600244 uint32_t memRefCount,
Chia-I Wue09b5362014-08-07 09:25:14 +0800245 const XGL_MEMORY_REF* pMemRefs)
246{
247 /*
248 * The winwys maintains the list of memory references. These are ignored
249 * until we move away from the winsys.
250 */
251 return XGL_SUCCESS;
252}
253
Chia-I Wu96177272015-01-03 15:27:41 +0800254ICD_EXPORT XGL_RESULT XGLAPI xglQueueWaitIdle(
Chia-I Wue09b5362014-08-07 09:25:14 +0800255 XGL_QUEUE queue_)
256{
257 struct intel_queue *queue = intel_queue(queue_);
258
259 return intel_queue_wait(queue, -1);
260}
Chia-I Wu251e7d92014-08-19 13:35:42 +0800261
Chia-I Wu96177272015-01-03 15:27:41 +0800262ICD_EXPORT XGL_RESULT XGLAPI xglQueueSubmit(
Chia-I Wuc5438c22014-08-19 14:03:06 +0800263 XGL_QUEUE queue_,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600264 uint32_t cmdBufferCount,
Chia-I Wu251e7d92014-08-19 13:35:42 +0800265 const XGL_CMD_BUFFER* pCmdBuffers,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600266 uint32_t memRefCount,
Chia-I Wu251e7d92014-08-19 13:35:42 +0800267 const XGL_MEMORY_REF* pMemRefs,
Chia-I Wuc5438c22014-08-19 14:03:06 +0800268 XGL_FENCE fence_)
Chia-I Wu251e7d92014-08-19 13:35:42 +0800269{
Chia-I Wuc5438c22014-08-19 14:03:06 +0800270 struct intel_queue *queue = intel_queue(queue_);
271 XGL_RESULT ret = XGL_SUCCESS;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600272 uint32_t i;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800273
274 for (i = 0; i < cmdBufferCount; i++) {
275 struct intel_cmd *cmd = intel_cmd(pCmdBuffers[i]);
Chia-I Wu465fe212015-02-11 11:27:06 -0700276 uint32_t active[2], pending[2];
Chia-I Wu94d2fba2014-08-25 11:38:08 +0800277 struct intel_bo *bo;
278 XGL_GPU_SIZE used;
279 XGL_RESULT ret;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800280
Chia-I Wuec841722014-08-25 22:36:01 +0800281 ret = queue_select_pipeline(queue, cmd->pipeline_select);
Chia-I Wu63883292014-08-25 13:50:26 +0800282 if (ret != XGL_SUCCESS)
283 break;
284
Chia-I Wufb6d3382015-02-11 11:23:52 -0700285 if (cmd->result != XGL_SUCCESS) {
286 intel_dev_log(cmd->dev, XGL_DBG_MSG_ERROR,
287 XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE, 0, 0,
288 "invalid command buffer submitted");
289 ret = cmd->result;
290 break;
291 }
292
Chia-I Wu465fe212015-02-11 11:27:06 -0700293 if (intel_debug & INTEL_DEBUG_HANG) {
294 intel_winsys_read_reset_stats(queue->dev->winsys,
295 &active[0], &pending[0]);
296 }
297
Chia-I Wu94d2fba2014-08-25 11:38:08 +0800298 bo = intel_cmd_get_batch(cmd, &used);
299 ret = queue_submit_bo(queue, bo, used);
300 queue->last_submitted_cmd = cmd;
301
Chia-I Wu465fe212015-02-11 11:27:06 -0700302 if ((intel_debug & INTEL_DEBUG_HANG) && ret == XGL_SUCCESS) {
303 intel_bo_wait(bo, -1);
304 intel_winsys_read_reset_stats(queue->dev->winsys,
305 &active[1], &pending[1]);
306
307 if (active[0] != active[1] || pending[0] != pending[1]) {
308 queue_submit_hang(queue, cmd, active[1] - active[0],
309 pending[1] - pending[0]);
310 }
311 }
312
Chia-I Wu00b51a82014-09-09 12:07:37 +0800313 if (intel_debug & INTEL_DEBUG_BATCH)
Chia-I Wu465fe212015-02-11 11:27:06 -0700314 intel_cmd_decode(cmd, false);
Chia-I Wu00b51a82014-09-09 12:07:37 +0800315
Chia-I Wuc5438c22014-08-19 14:03:06 +0800316 if (ret != XGL_SUCCESS)
317 break;
318 }
319
320 if (ret == XGL_SUCCESS && fence_ != XGL_NULL_HANDLE) {
321 struct intel_fence *fence = intel_fence(fence_);
322 intel_fence_set_cmd(fence, queue->last_submitted_cmd);
323 }
324
325 /* XGL_MEMORY_REFs are ignored as the winsys already knows them */
326
327 return ret;
Chia-I Wu251e7d92014-08-19 13:35:42 +0800328}
329
Chia-I Wu96177272015-01-03 15:27:41 +0800330ICD_EXPORT XGL_RESULT XGLAPI xglOpenSharedQueueSemaphore(
Chia-I Wu251e7d92014-08-19 13:35:42 +0800331 XGL_DEVICE device,
332 const XGL_QUEUE_SEMAPHORE_OPEN_INFO* pOpenInfo,
333 XGL_QUEUE_SEMAPHORE* pSemaphore)
334{
335 return XGL_ERROR_UNAVAILABLE;
336}
337
Chia-I Wu96177272015-01-03 15:27:41 +0800338ICD_EXPORT XGL_RESULT XGLAPI xglCreateQueueSemaphore(
Chia-I Wu251e7d92014-08-19 13:35:42 +0800339 XGL_DEVICE device,
340 const XGL_QUEUE_SEMAPHORE_CREATE_INFO* pCreateInfo,
341 XGL_QUEUE_SEMAPHORE* pSemaphore)
342{
343 /*
344 * We want to find an unused semaphore register and initialize it. Signal
345 * will increment the register. Wait will atomically decrement it and
346 * block if the value is zero, or a large constant N if we do not want to
347 * go negative.
348 *
349 * XXX However, MI_SEMAPHORE_MBOX does not seem to have the flexibility.
350 */
351 return XGL_ERROR_UNAVAILABLE;
352}
353
Chia-I Wu96177272015-01-03 15:27:41 +0800354ICD_EXPORT XGL_RESULT XGLAPI xglSignalQueueSemaphore(
Chia-I Wu251e7d92014-08-19 13:35:42 +0800355 XGL_QUEUE queue,
356 XGL_QUEUE_SEMAPHORE semaphore)
357{
358 return XGL_ERROR_UNAVAILABLE;
359}
360
Chia-I Wu96177272015-01-03 15:27:41 +0800361ICD_EXPORT XGL_RESULT XGLAPI xglWaitQueueSemaphore(
Chia-I Wu251e7d92014-08-19 13:35:42 +0800362 XGL_QUEUE queue,
363 XGL_QUEUE_SEMAPHORE semaphore)
364{
365 return XGL_ERROR_UNAVAILABLE;
366}