blob: dff89c8afc0fbe9f01c50970a32b695b9c79c5a3 [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.
23 */
24
Chia-I Wu3ad3c542014-08-25 11:09:17 +080025#include "genhw/genhw.h"
Chia-I Wue09b5362014-08-07 09:25:14 +080026#include "kmd/winsys.h"
Chia-I Wu34f45182014-08-19 14:02:59 +080027#include "cmd.h"
Chia-I Wue09b5362014-08-07 09:25:14 +080028#include "dev.h"
Chia-I Wuc5438c22014-08-19 14:03:06 +080029#include "fence.h"
Chia-I Wue09b5362014-08-07 09:25:14 +080030#include "queue.h"
31
Chia-I Wu63883292014-08-25 13:50:26 +080032/* must match intel_cmd::pipeline_select */
33enum queue_state {
34 QUEUE_STATE_GRAPHICS_SELECTED = GEN6_PIPELINE_SELECT_DW0_SELECT_3D,
35 QUEUE_STATE_COMPUTE_SELECTED = GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA,
36 QUEUE_STATE_INITIALIZED = -1,
37};
38
Chia-I Wu94d2fba2014-08-25 11:38:08 +080039static XGL_RESULT queue_submit_bo(struct intel_queue *queue,
40 struct intel_bo *bo,
41 XGL_GPU_SIZE used)
42{
43 struct intel_winsys *winsys = queue->dev->winsys;
44 int err;
45
46 if (intel_debug & INTEL_DEBUG_BATCH)
47 intel_winsys_decode_bo(winsys, bo, used);
48
49 if (intel_debug & INTEL_DEBUG_NOHW)
50 err = 0;
51 else
52 err = intel_winsys_submit_bo(winsys, queue->ring, bo, used, 0);
53
54 return (err) ? XGL_ERROR_UNKNOWN : XGL_SUCCESS;
55}
56
Chia-I Wu63883292014-08-25 13:50:26 +080057static XGL_RESULT queue_set_state(struct intel_queue *queue,
58 enum queue_state state)
Chia-I Wu3ad3c542014-08-25 11:09:17 +080059{
Chia-I Wu63883292014-08-25 13:50:26 +080060 static const uint32_t queue_state_init[] = {
61 /* STATE_SIP */
62 GEN_RENDER_CMD(COMMON, GEN6, STATE_SIP),
63 0,
64 /* PIPELINE_SELECT */
65 GEN_RENDER_CMD(SINGLE_DW, GEN6, PIPELINE_SELECT) |
66 GEN6_PIPELINE_SELECT_DW0_SELECT_3D,
67 /* 3DSTATE_VF_STATISTICS */
68 GEN_RENDER_CMD(SINGLE_DW, GEN6, 3DSTATE_VF_STATISTICS),
69 /* end */
70 GEN_MI_CMD(MI_BATCH_BUFFER_END),
71 GEN_MI_CMD(MI_NOOP),
72 };
73 static const uint32_t queue_state_select_graphics[] = {
74 /* PIPELINE_SELECT */
75 GEN_RENDER_CMD(SINGLE_DW, GEN6, PIPELINE_SELECT) |
76 GEN6_PIPELINE_SELECT_DW0_SELECT_3D,
77 /* end */
78 GEN_MI_CMD(MI_BATCH_BUFFER_END),
79 };
80 static const uint32_t queue_state_select_compute[] = {
81 /* PIPELINE_SELECT */
82 GEN_RENDER_CMD(SINGLE_DW, GEN6, PIPELINE_SELECT) |
83 GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA,
84 /* end */
85 GEN_MI_CMD(MI_BATCH_BUFFER_END),
86 };
Chia-I Wu3ad3c542014-08-25 11:09:17 +080087 struct intel_bo *bo;
Chia-I Wu63883292014-08-25 13:50:26 +080088 XGL_GPU_SIZE size;
Chia-I Wu3ad3c542014-08-25 11:09:17 +080089 XGL_RESULT ret;
90
Chia-I Wu63883292014-08-25 13:50:26 +080091 if (queue->last_pipeline_select == state)
92 return XGL_SUCCESS;
Chia-I Wu3ad3c542014-08-25 11:09:17 +080093
Chia-I Wu63883292014-08-25 13:50:26 +080094 switch (state) {
95 case QUEUE_STATE_GRAPHICS_SELECTED:
96 bo = queue->select_graphics_bo;
97 size = sizeof(queue_state_select_graphics);
98 break;
99 case QUEUE_STATE_COMPUTE_SELECTED:
100 bo = queue->select_compute_bo;
101 size = sizeof(queue_state_select_compute);
102 break;
103 case QUEUE_STATE_INITIALIZED:
104 /* will be reused for the atomic counters */
105 assert(!queue->atomic_bo);
106 bo = NULL;
107 size = sizeof(queue_state_init);
108 break;
109 default:
110 return XGL_ERROR_INVALID_VALUE;
111 break;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800112 }
113
Chia-I Wu63883292014-08-25 13:50:26 +0800114 if (!bo) {
115 const void *cmd;
116 void *ptr;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800117
Chia-I Wu63883292014-08-25 13:50:26 +0800118 bo = intel_winsys_alloc_buffer(queue->dev->winsys,
119 "queue bo", 4096, INTEL_DOMAIN_CPU);
120 if (!bo)
121 return XGL_ERROR_OUT_OF_GPU_MEMORY;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800122
Chia-I Wu63883292014-08-25 13:50:26 +0800123 /* do the allocation only */
124 if (queue->ring != INTEL_RING_RENDER) {
125 assert(state == QUEUE_STATE_INITIALIZED);
126 queue->atomic_bo = bo;
127 queue->last_pipeline_select = QUEUE_STATE_INITIALIZED;
128 return XGL_SUCCESS;
129 }
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800130
Chia-I Wu63883292014-08-25 13:50:26 +0800131 ptr = intel_bo_map(bo, true);
132 if (!ptr) {
133 intel_bo_unreference(bo);
134 return XGL_ERROR_MEMORY_MAP_FAILED;
135 }
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800136
Chia-I Wu63883292014-08-25 13:50:26 +0800137 switch (state) {
138 case QUEUE_STATE_GRAPHICS_SELECTED:
139 queue->select_graphics_bo = bo;
140 cmd = queue_state_select_graphics;
141 break;
142 case QUEUE_STATE_COMPUTE_SELECTED:
143 queue->select_compute_bo = bo;
144 cmd = queue_state_select_compute;
145 break;
146 case QUEUE_STATE_INITIALIZED:
147 /* reused for the atomic counters */
148 queue->atomic_bo = bo;
149 cmd = queue_state_init;
150 break;
151 default:
152 break;
153 }
154
155 memcpy(ptr, cmd, size);
156 intel_bo_unmap(bo);
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800157 }
158
Chia-I Wu63883292014-08-25 13:50:26 +0800159 assert(queue->ring == INTEL_RING_RENDER);
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800160
Chia-I Wu63883292014-08-25 13:50:26 +0800161 ret = queue_submit_bo(queue, bo, size);
162 if (ret == XGL_SUCCESS) {
163 if (state == QUEUE_STATE_INITIALIZED)
164 state = QUEUE_STATE_GRAPHICS_SELECTED;
165 queue->last_pipeline_select = state;
166 }
167
168 return ret;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800169}
170
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800171XGL_RESULT intel_queue_create(struct intel_dev *dev,
Chia-I Wucdcff732014-08-19 14:44:15 +0800172 enum intel_gpu_engine_type engine,
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800173 struct intel_queue **queue_ret)
Chia-I Wue09b5362014-08-07 09:25:14 +0800174{
175 struct intel_queue *queue;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800176 enum intel_ring_type ring;
177
Chia-I Wucdcff732014-08-19 14:44:15 +0800178 switch (engine) {
179 case INTEL_GPU_ENGINE_3D:
Chia-I Wuc5438c22014-08-19 14:03:06 +0800180 ring = INTEL_RING_RENDER;
181 break;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800182 default:
183 return XGL_ERROR_INVALID_VALUE;
184 break;
185 }
Chia-I Wue09b5362014-08-07 09:25:14 +0800186
Courtney Goeltzenleuchterfb4fb532014-08-14 09:35:21 -0600187 queue = (struct intel_queue *) intel_base_create(dev, sizeof(*queue),
Chia-I Wubbf2c932014-08-07 12:20:08 +0800188 dev->base.dbg, XGL_DBG_OBJECT_QUEUE, NULL, 0);
Chia-I Wue09b5362014-08-07 09:25:14 +0800189 if (!queue)
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800190 return XGL_ERROR_OUT_OF_MEMORY;
Chia-I Wue09b5362014-08-07 09:25:14 +0800191
Chia-I Wue09b5362014-08-07 09:25:14 +0800192 queue->dev = dev;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800193 queue->ring = ring;
Chia-I Wue09b5362014-08-07 09:25:14 +0800194
Chia-I Wu63883292014-08-25 13:50:26 +0800195 if (queue_set_state(queue, QUEUE_STATE_INITIALIZED) != XGL_SUCCESS) {
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800196 intel_queue_destroy(queue);
Chia-I Wu63883292014-08-25 13:50:26 +0800197 return XGL_ERROR_INITIALIZATION_FAILED;
Chia-I Wu3ad3c542014-08-25 11:09:17 +0800198 }
199
Chia-I Wu9ae59c12014-08-07 10:08:49 +0800200 *queue_ret = queue;
201
202 return XGL_SUCCESS;
Chia-I Wue09b5362014-08-07 09:25:14 +0800203}
204
205void intel_queue_destroy(struct intel_queue *queue)
206{
Chia-I Wu63883292014-08-25 13:50:26 +0800207 if (queue->atomic_bo)
208 intel_bo_unreference(queue->atomic_bo);
209 if (queue->select_graphics_bo)
210 intel_bo_unreference(queue->select_graphics_bo);
211 if (queue->select_compute_bo)
212 intel_bo_unreference(queue->select_compute_bo);
Chia-I Wubbf2c932014-08-07 12:20:08 +0800213 intel_base_destroy(&queue->base);
Chia-I Wue09b5362014-08-07 09:25:14 +0800214}
215
216XGL_RESULT intel_queue_wait(struct intel_queue *queue, int64_t timeout)
217{
Chia-I Wue24c3292014-08-21 14:05:23 +0800218 struct intel_bo *bo = (queue->last_submitted_cmd) ?
219 intel_cmd_get_batch(queue->last_submitted_cmd, NULL) : NULL;
Chia-I Wue09b5362014-08-07 09:25:14 +0800220
Chia-I Wue24c3292014-08-21 14:05:23 +0800221 return (!bo || intel_bo_wait(bo, timeout) == 0) ?
Chia-I Wue09b5362014-08-07 09:25:14 +0800222 XGL_SUCCESS : XGL_ERROR_UNKNOWN;
223}
224
225XGL_RESULT XGLAPI intelQueueSetGlobalMemReferences(
226 XGL_QUEUE queue,
227 XGL_UINT memRefCount,
228 const XGL_MEMORY_REF* pMemRefs)
229{
230 /*
231 * The winwys maintains the list of memory references. These are ignored
232 * until we move away from the winsys.
233 */
234 return XGL_SUCCESS;
235}
236
237XGL_RESULT XGLAPI intelQueueWaitIdle(
238 XGL_QUEUE queue_)
239{
240 struct intel_queue *queue = intel_queue(queue_);
241
242 return intel_queue_wait(queue, -1);
243}
Chia-I Wu251e7d92014-08-19 13:35:42 +0800244
245XGL_RESULT XGLAPI intelQueueSubmit(
Chia-I Wuc5438c22014-08-19 14:03:06 +0800246 XGL_QUEUE queue_,
Chia-I Wu251e7d92014-08-19 13:35:42 +0800247 XGL_UINT cmdBufferCount,
248 const XGL_CMD_BUFFER* pCmdBuffers,
249 XGL_UINT memRefCount,
250 const XGL_MEMORY_REF* pMemRefs,
Chia-I Wuc5438c22014-08-19 14:03:06 +0800251 XGL_FENCE fence_)
Chia-I Wu251e7d92014-08-19 13:35:42 +0800252{
Chia-I Wuc5438c22014-08-19 14:03:06 +0800253 struct intel_queue *queue = intel_queue(queue_);
254 XGL_RESULT ret = XGL_SUCCESS;
255 XGL_UINT i;
256
257 for (i = 0; i < cmdBufferCount; i++) {
258 struct intel_cmd *cmd = intel_cmd(pCmdBuffers[i]);
Chia-I Wu94d2fba2014-08-25 11:38:08 +0800259 struct intel_bo *bo;
260 XGL_GPU_SIZE used;
261 XGL_RESULT ret;
Chia-I Wuc5438c22014-08-19 14:03:06 +0800262
Chia-I Wu63883292014-08-25 13:50:26 +0800263 ret = queue_set_state(queue, cmd->pipeline_select);
264 if (ret != XGL_SUCCESS)
265 break;
266
Chia-I Wu94d2fba2014-08-25 11:38:08 +0800267 bo = intel_cmd_get_batch(cmd, &used);
268 ret = queue_submit_bo(queue, bo, used);
269 queue->last_submitted_cmd = cmd;
270
Chia-I Wuc5438c22014-08-19 14:03:06 +0800271 if (ret != XGL_SUCCESS)
272 break;
273 }
274
275 if (ret == XGL_SUCCESS && fence_ != XGL_NULL_HANDLE) {
276 struct intel_fence *fence = intel_fence(fence_);
277 intel_fence_set_cmd(fence, queue->last_submitted_cmd);
278 }
279
280 /* XGL_MEMORY_REFs are ignored as the winsys already knows them */
281
282 return ret;
Chia-I Wu251e7d92014-08-19 13:35:42 +0800283}
284
285XGL_RESULT XGLAPI intelOpenSharedQueueSemaphore(
286 XGL_DEVICE device,
287 const XGL_QUEUE_SEMAPHORE_OPEN_INFO* pOpenInfo,
288 XGL_QUEUE_SEMAPHORE* pSemaphore)
289{
290 return XGL_ERROR_UNAVAILABLE;
291}
292
293XGL_RESULT XGLAPI intelCreateQueueSemaphore(
294 XGL_DEVICE device,
295 const XGL_QUEUE_SEMAPHORE_CREATE_INFO* pCreateInfo,
296 XGL_QUEUE_SEMAPHORE* pSemaphore)
297{
298 /*
299 * We want to find an unused semaphore register and initialize it. Signal
300 * will increment the register. Wait will atomically decrement it and
301 * block if the value is zero, or a large constant N if we do not want to
302 * go negative.
303 *
304 * XXX However, MI_SEMAPHORE_MBOX does not seem to have the flexibility.
305 */
306 return XGL_ERROR_UNAVAILABLE;
307}
308
309XGL_RESULT XGLAPI intelSignalQueueSemaphore(
310 XGL_QUEUE queue,
311 XGL_QUEUE_SEMAPHORE semaphore)
312{
313 return XGL_ERROR_UNAVAILABLE;
314}
315
316XGL_RESULT XGLAPI intelWaitQueueSemaphore(
317 XGL_QUEUE queue,
318 XGL_QUEUE_SEMAPHORE semaphore)
319{
320 return XGL_ERROR_UNAVAILABLE;
321}