blob: 2a8fba1d588a3aa49db5e85ecccbb624fd7b9a2d [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 Wu94d2fba2014-08-25 11:38:08 +080035static XGL_RESULT queue_submit_bo(struct intel_queue *queue,
36 struct intel_bo *bo,
37 XGL_GPU_SIZE used)
38{
39 struct intel_winsys *winsys = queue->dev->winsys;
40 int err;
41
42 if (intel_debug & INTEL_DEBUG_BATCH)
43 intel_winsys_decode_bo(winsys, bo, used);
44
45 if (intel_debug & INTEL_DEBUG_NOHW)
46 err = 0;
47 else
48 err = intel_winsys_submit_bo(winsys, queue->ring, bo, used, 0);
49
50 return (err) ? XGL_ERROR_UNKNOWN : XGL_SUCCESS;
51}
52
Chia-I Wuec841722014-08-25 22:36:01 +080053static struct intel_bo *queue_create_bo(struct intel_queue *queue,
54 XGL_GPU_SIZE size,
55 const void *cmd,
56 XGL_SIZE cmd_len)
Chia-I Wu3ad3c542014-08-25 11:09:17 +080057{
Chia-I Wuec841722014-08-25 22:36:01 +080058 struct intel_bo *bo;
59 void *ptr;
60
61 bo = intel_winsys_alloc_buffer(queue->dev->winsys,
Chia-I Wu32a22462014-08-26 14:13:46 +080062 "queue bo", size, true);
Chia-I Wuec841722014-08-25 22:36:01 +080063 if (!bo)
64 return NULL;
65
66 if (!cmd_len)
67 return bo;
68
69 ptr = intel_bo_map(bo, true);
70 if (!ptr) {
71 intel_bo_unreference(bo);
72 return NULL;
73 }
74
75 memcpy(ptr, cmd, cmd_len);
76 intel_bo_unmap(bo);
77
78 return bo;
79}
80
81static XGL_RESULT queue_select_pipeline(struct intel_queue *queue,
82 int pipeline_select)
83{
84 uint32_t pipeline_select_cmd[] = {
Chia-I Wu426072d2014-08-26 14:31:55 +080085 GEN6_RENDER_CMD(SINGLE_DW, PIPELINE_SELECT),
86 GEN6_MI_CMD(MI_BATCH_BUFFER_END),
Chia-I Wuec841722014-08-25 22:36:01 +080087 };
88 struct intel_bo *bo;
89 XGL_RESULT ret;
90
91 if (queue->ring != INTEL_RING_RENDER ||
92 queue->last_pipeline_select == pipeline_select)
93 return XGL_SUCCESS;
94
95 switch (pipeline_select) {
96 case GEN6_PIPELINE_SELECT_DW0_SELECT_3D:
97 bo = queue->select_graphics_bo;
98 break;
99 case GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA:
100 bo = queue->select_compute_bo;
101 break;
102 default:
103 return XGL_ERROR_INVALID_VALUE;
104 break;
105 }
106
107 if (!bo) {
108 pipeline_select_cmd[0] |= pipeline_select;
109 bo = queue_create_bo(queue, sizeof(pipeline_select_cmd),
110 pipeline_select_cmd, sizeof(pipeline_select_cmd));
111 if (!bo)
112 return XGL_ERROR_OUT_OF_GPU_MEMORY;
113
114 switch (pipeline_select) {
115 case GEN6_PIPELINE_SELECT_DW0_SELECT_3D:
116 queue->select_graphics_bo = bo;
117 break;
118 case GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA:
119 queue->select_compute_bo = bo;
120 break;
121 default:
122 break;
123 }
124 }
125
126 ret = queue_submit_bo(queue, bo, sizeof(pipeline_select_cmd));
127 if (ret == XGL_SUCCESS)
128 queue->last_pipeline_select = pipeline_select;
129
130 return ret;
131}
132
133static XGL_RESULT queue_init_hw_and_atomic_bo(struct intel_queue *queue)
134{
135 const uint32_t ctx_init_cmd[] = {
Chia-I Wu63883292014-08-25 13:50:26 +0800136 /* STATE_SIP */
Chia-I Wu426072d2014-08-26 14:31:55 +0800137 GEN6_RENDER_CMD(COMMON, STATE_SIP),
Chia-I Wu63883292014-08-25 13:50:26 +0800138 0,
139 /* PIPELINE_SELECT */
Chia-I Wu426072d2014-08-26 14:31:55 +0800140 GEN6_RENDER_CMD(SINGLE_DW, PIPELINE_SELECT) |
Chia-I Wu63883292014-08-25 13:50:26 +0800141 GEN6_PIPELINE_SELECT_DW0_SELECT_3D,
142 /* 3DSTATE_VF_STATISTICS */
Chia-I Wu426072d2014-08-26 14:31:55 +0800143 GEN6_RENDER_CMD(SINGLE_DW, 3DSTATE_VF_STATISTICS),
Chia-I Wu63883292014-08-25 13:50:26 +0800144 /* end */
Chia-I Wu426072d2014-08-26 14:31:55 +0800145 GEN6_MI_CMD(MI_BATCH_BUFFER_END),
146 GEN6_MI_CMD(MI_NOOP),
Chia-I Wu63883292014-08-25 13:50:26 +0800147 };
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800148 struct intel_bo *bo;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800149 XGL_RESULT ret;
150
Chia-I Wuec841722014-08-25 22:36:01 +0800151 if (queue->ring != INTEL_RING_RENDER) {
152 queue->last_pipeline_select = -1;
153 queue->atomic_bo = queue_create_bo(queue,
154 sizeof(uint32_t) * INTEL_QUEUE_ATOMIC_COUNTER_COUNT,
155 NULL, 0);
156 return (queue->atomic_bo) ? XGL_SUCCESS : XGL_ERROR_OUT_OF_GPU_MEMORY;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800157 }
158
Chia-I Wuec841722014-08-25 22:36:01 +0800159 bo = queue_create_bo(queue,
160 sizeof(uint32_t) * INTEL_QUEUE_ATOMIC_COUNTER_COUNT,
161 ctx_init_cmd, sizeof(ctx_init_cmd));
162 if (!bo)
163 return XGL_ERROR_OUT_OF_GPU_MEMORY;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800164
Chia-I Wuec841722014-08-25 22:36:01 +0800165 ret = queue_submit_bo(queue, bo, sizeof(ctx_init_cmd));
166 if (ret != XGL_SUCCESS) {
167 intel_bo_unreference(bo);
168 return ret;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800169 }
170
Chia-I Wuec841722014-08-25 22:36:01 +0800171 queue->last_pipeline_select = GEN6_PIPELINE_SELECT_DW0_SELECT_3D;
172 /* reuse */
173 queue->atomic_bo = bo;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800174
Chia-I Wuec841722014-08-25 22:36:01 +0800175 return XGL_SUCCESS;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800176}
177
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800178XGL_RESULT intel_queue_create(struct intel_dev *dev,
Chia-I Wucdcff732014-08-19 14:44:15 +0800179 enum intel_gpu_engine_type engine,
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800180 struct intel_queue **queue_ret)
Chia-I Wue09b5362014-08-07 09:25:14 +0800181{
182 struct intel_queue *queue;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800183 enum intel_ring_type ring;
184
Chia-I Wucdcff732014-08-19 14:44:15 +0800185 switch (engine) {
186 case INTEL_GPU_ENGINE_3D:
Chia-I Wuc5438c22014-08-19 14:03:06 +0800187 ring = INTEL_RING_RENDER;
188 break;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800189 default:
190 return XGL_ERROR_INVALID_VALUE;
191 break;
192 }
Chia-I Wue09b5362014-08-07 09:25:14 +0800193
Courtney Goeltzenleuchterfb4fb532014-08-14 09:35:21 -0600194 queue = (struct intel_queue *) intel_base_create(dev, sizeof(*queue),
Chia-I Wubbf2c932014-08-07 12:20:08 +0800195 dev->base.dbg, XGL_DBG_OBJECT_QUEUE, NULL, 0);
Chia-I Wue09b5362014-08-07 09:25:14 +0800196 if (!queue)
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800197 return XGL_ERROR_OUT_OF_MEMORY;
Chia-I Wue09b5362014-08-07 09:25:14 +0800198
Chia-I Wue09b5362014-08-07 09:25:14 +0800199 queue->dev = dev;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800200 queue->ring = ring;
Chia-I Wue09b5362014-08-07 09:25:14 +0800201
Chia-I Wuec841722014-08-25 22:36:01 +0800202 if (queue_init_hw_and_atomic_bo(queue) != XGL_SUCCESS) {
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800203 intel_queue_destroy(queue);
Chia-I Wu63883292014-08-25 13:50:26 +0800204 return XGL_ERROR_INITIALIZATION_FAILED;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800205 }
206
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800207 *queue_ret = queue;
208
209 return XGL_SUCCESS;
Chia-I Wue09b5362014-08-07 09:25:14 +0800210}
211
212void intel_queue_destroy(struct intel_queue *queue)
213{
Chia-I Wu63883292014-08-25 13:50:26 +0800214 if (queue->atomic_bo)
215 intel_bo_unreference(queue->atomic_bo);
216 if (queue->select_graphics_bo)
217 intel_bo_unreference(queue->select_graphics_bo);
218 if (queue->select_compute_bo)
219 intel_bo_unreference(queue->select_compute_bo);
Chia-I Wubbf2c932014-08-07 12:20:08 +0800220 intel_base_destroy(&queue->base);
Chia-I Wue09b5362014-08-07 09:25:14 +0800221}
222
223XGL_RESULT intel_queue_wait(struct intel_queue *queue, int64_t timeout)
224{
Chia-I Wue24c3292014-08-21 14:05:23 +0800225 struct intel_bo *bo = (queue->last_submitted_cmd) ?
226 intel_cmd_get_batch(queue->last_submitted_cmd, NULL) : NULL;
Chia-I Wue09b5362014-08-07 09:25:14 +0800227
Chia-I Wue24c3292014-08-21 14:05:23 +0800228 return (!bo || intel_bo_wait(bo, timeout) == 0) ?
Chia-I Wue09b5362014-08-07 09:25:14 +0800229 XGL_SUCCESS : XGL_ERROR_UNKNOWN;
230}
231
232XGL_RESULT XGLAPI intelQueueSetGlobalMemReferences(
233 XGL_QUEUE queue,
234 XGL_UINT memRefCount,
235 const XGL_MEMORY_REF* pMemRefs)
236{
237 /*
238 * The winwys maintains the list of memory references. These are ignored
239 * until we move away from the winsys.
240 */
241 return XGL_SUCCESS;
242}
243
244XGL_RESULT XGLAPI intelQueueWaitIdle(
245 XGL_QUEUE queue_)
246{
247 struct intel_queue *queue = intel_queue(queue_);
248
249 return intel_queue_wait(queue, -1);
250}
Chia-I Wu251e7d92014-08-19 13:35:42 +0800251
252XGL_RESULT XGLAPI intelQueueSubmit(
Chia-I Wuc5438c22014-08-19 14:03:06 +0800253 XGL_QUEUE queue_,
Chia-I Wu251e7d92014-08-19 13:35:42 +0800254 XGL_UINT cmdBufferCount,
255 const XGL_CMD_BUFFER* pCmdBuffers,
256 XGL_UINT memRefCount,
257 const XGL_MEMORY_REF* pMemRefs,
Chia-I Wuc5438c22014-08-19 14:03:06 +0800258 XGL_FENCE fence_)
Chia-I Wu251e7d92014-08-19 13:35:42 +0800259{
Chia-I Wuc5438c22014-08-19 14:03:06 +0800260 struct intel_queue *queue = intel_queue(queue_);
261 XGL_RESULT ret = XGL_SUCCESS;
262 XGL_UINT i;
263
264 for (i = 0; i < cmdBufferCount; i++) {
265 struct intel_cmd *cmd = intel_cmd(pCmdBuffers[i]);
Chia-I Wu94d2fba2014-08-25 11:38:08 +0800266 struct intel_bo *bo;
267 XGL_GPU_SIZE used;
268 XGL_RESULT ret;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800269
Chia-I Wuec841722014-08-25 22:36:01 +0800270 ret = queue_select_pipeline(queue, cmd->pipeline_select);
Chia-I Wu63883292014-08-25 13:50:26 +0800271 if (ret != XGL_SUCCESS)
272 break;
273
Chia-I Wu94d2fba2014-08-25 11:38:08 +0800274 bo = intel_cmd_get_batch(cmd, &used);
275 ret = queue_submit_bo(queue, bo, used);
276 queue->last_submitted_cmd = cmd;
277
Chia-I Wuc5438c22014-08-19 14:03:06 +0800278 if (ret != XGL_SUCCESS)
279 break;
280 }
281
282 if (ret == XGL_SUCCESS && fence_ != XGL_NULL_HANDLE) {
283 struct intel_fence *fence = intel_fence(fence_);
284 intel_fence_set_cmd(fence, queue->last_submitted_cmd);
285 }
286
287 /* XGL_MEMORY_REFs are ignored as the winsys already knows them */
288
289 return ret;
Chia-I Wu251e7d92014-08-19 13:35:42 +0800290}
291
292XGL_RESULT XGLAPI intelOpenSharedQueueSemaphore(
293 XGL_DEVICE device,
294 const XGL_QUEUE_SEMAPHORE_OPEN_INFO* pOpenInfo,
295 XGL_QUEUE_SEMAPHORE* pSemaphore)
296{
297 return XGL_ERROR_UNAVAILABLE;
298}
299
300XGL_RESULT XGLAPI intelCreateQueueSemaphore(
301 XGL_DEVICE device,
302 const XGL_QUEUE_SEMAPHORE_CREATE_INFO* pCreateInfo,
303 XGL_QUEUE_SEMAPHORE* pSemaphore)
304{
305 /*
306 * We want to find an unused semaphore register and initialize it. Signal
307 * will increment the register. Wait will atomically decrement it and
308 * block if the value is zero, or a large constant N if we do not want to
309 * go negative.
310 *
311 * XXX However, MI_SEMAPHORE_MBOX does not seem to have the flexibility.
312 */
313 return XGL_ERROR_UNAVAILABLE;
314}
315
316XGL_RESULT XGLAPI intelSignalQueueSemaphore(
317 XGL_QUEUE queue,
318 XGL_QUEUE_SEMAPHORE semaphore)
319{
320 return XGL_ERROR_UNAVAILABLE;
321}
322
323XGL_RESULT XGLAPI intelWaitQueueSemaphore(
324 XGL_QUEUE queue,
325 XGL_QUEUE_SEMAPHORE semaphore)
326{
327 return XGL_ERROR_UNAVAILABLE;
328}