i965/nir/vec4: Implement load_const intrinsic
[mesa.git] / src / mesa / drivers / dri / i965 / intel_syncobj.c
1 /*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 *
26 */
27
28 /**
29 * \file
30 * \brief Support for GL_ARB_sync and EGL_KHR_fence_sync.
31 *
32 * GL_ARB_sync is implemented by flushing the current batchbuffer and keeping a
33 * reference on it. We can then check for completion or wait for completion
34 * using the normal buffer object mechanisms. This does mean that if an
35 * application is using many sync objects, it will emit small batchbuffers
36 * which may end up being a significant overhead. In other tests of removing
37 * gratuitous batchbuffer syncs in Mesa, it hasn't appeared to be a significant
38 * performance bottleneck, though.
39 */
40
41 #include "main/imports.h"
42
43 #include "brw_context.h"
44 #include "intel_batchbuffer.h"
45 #include "intel_reg.h"
46
47 struct brw_fence {
48 /** The fence waits for completion of this batch. */
49 drm_intel_bo *batch_bo;
50
51 bool signalled;
52 };
53
54 struct intel_gl_sync_object {
55 struct gl_sync_object Base;
56 struct brw_fence fence;
57 };
58
59 static void
60 brw_fence_finish(struct brw_fence *fence)
61 {
62 if (fence->batch_bo)
63 drm_intel_bo_unreference(fence->batch_bo);
64 }
65
66 static void
67 brw_fence_insert(struct brw_context *brw, struct brw_fence *fence)
68 {
69 assert(!fence->batch_bo);
70 assert(!fence->signalled);
71
72 brw_emit_mi_flush(brw);
73 fence->batch_bo = brw->batch.bo;
74 drm_intel_bo_reference(fence->batch_bo);
75 intel_batchbuffer_flush(brw);
76 }
77
78 static bool
79 brw_fence_has_completed(struct brw_fence *fence)
80 {
81 if (fence->signalled)
82 return true;
83
84 if (fence->batch_bo && !drm_intel_bo_busy(fence->batch_bo)) {
85 drm_intel_bo_unreference(fence->batch_bo);
86 fence->batch_bo = NULL;
87 fence->signalled = true;
88 return true;
89 }
90
91 return false;
92 }
93
94 /**
95 * Return true if the function successfully signals or has already signalled.
96 * (This matches the behavior expected from __DRI2fence::client_wait_sync).
97 */
98 static bool
99 brw_fence_client_wait(struct brw_context *brw, struct brw_fence *fence,
100 uint64_t timeout)
101 {
102 if (fence->signalled)
103 return true;
104
105 assert(fence->batch_bo);
106
107 /* DRM_IOCTL_I915_GEM_WAIT uses a signed 64 bit timeout and returns
108 * immediately for timeouts <= 0. The best we can do is to clamp the
109 * timeout to INT64_MAX. This limits the maximum timeout from 584 years to
110 * 292 years - likely not a big deal.
111 */
112 if (timeout > INT64_MAX)
113 timeout = INT64_MAX;
114
115 if (drm_intel_gem_bo_wait(fence->batch_bo, timeout) != 0)
116 return false;
117
118 fence->signalled = true;
119 drm_intel_bo_unreference(fence->batch_bo);
120 fence->batch_bo = NULL;
121
122 return true;
123 }
124
125 static void
126 brw_fence_server_wait(struct brw_context *brw, struct brw_fence *fence)
127 {
128 /* We have nothing to do for WaitSync. Our GL command stream is sequential,
129 * so given that the sync object has already flushed the batchbuffer, any
130 * batchbuffers coming after this waitsync will naturally not occur until
131 * the previous one is done.
132 */
133 }
134
135 static struct gl_sync_object *
136 intel_gl_new_sync_object(struct gl_context *ctx, GLuint id)
137 {
138 struct intel_gl_sync_object *sync;
139
140 sync = calloc(1, sizeof(*sync));
141 if (!sync)
142 return NULL;
143
144 return &sync->Base;
145 }
146
147 static void
148 intel_gl_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *s)
149 {
150 struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
151
152 brw_fence_finish(&sync->fence);
153 free(sync);
154 }
155
156 static void
157 intel_gl_fence_sync(struct gl_context *ctx, struct gl_sync_object *s,
158 GLenum condition, GLbitfield flags)
159 {
160 struct brw_context *brw = brw_context(ctx);
161 struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
162
163 brw_fence_insert(brw, &sync->fence);
164 }
165
166 static void
167 intel_gl_client_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
168 GLbitfield flags, GLuint64 timeout)
169 {
170 struct brw_context *brw = brw_context(ctx);
171 struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
172
173 if (brw_fence_client_wait(brw, &sync->fence, timeout))
174 s->StatusFlag = 1;
175 }
176
177 static void
178 intel_gl_server_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
179 GLbitfield flags, GLuint64 timeout)
180 {
181 struct brw_context *brw = brw_context(ctx);
182 struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
183
184 brw_fence_server_wait(brw, &sync->fence);
185 }
186
187 static void
188 intel_gl_check_sync(struct gl_context *ctx, struct gl_sync_object *s)
189 {
190 struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
191
192 if (brw_fence_has_completed(&sync->fence))
193 s->StatusFlag = 1;
194 }
195
196 void
197 intel_init_syncobj_functions(struct dd_function_table *functions)
198 {
199 functions->NewSyncObject = intel_gl_new_sync_object;
200 functions->DeleteSyncObject = intel_gl_delete_sync_object;
201 functions->FenceSync = intel_gl_fence_sync;
202 functions->CheckSync = intel_gl_check_sync;
203 functions->ClientWaitSync = intel_gl_client_wait_sync;
204 functions->ServerWaitSync = intel_gl_server_wait_sync;
205 }
206
207 static void *
208 intel_dri_create_fence(__DRIcontext *ctx)
209 {
210 struct brw_context *brw = ctx->driverPrivate;
211 struct brw_fence *fence;
212
213 fence = calloc(1, sizeof(*fence));
214 if (!fence)
215 return NULL;
216
217 brw_fence_insert(brw, fence);
218
219 return fence;
220 }
221
222 static void
223 intel_dri_destroy_fence(__DRIscreen *screen, void *driver_fence)
224 {
225 struct brw_fence *fence = driver_fence;
226
227 brw_fence_finish(fence);
228 free(fence);
229 }
230
231 static GLboolean
232 intel_dri_client_wait_sync(__DRIcontext *ctx, void *driver_fence, unsigned flags,
233 uint64_t timeout)
234 {
235 struct brw_context *brw = ctx->driverPrivate;
236 struct brw_fence *fence = driver_fence;
237
238 return brw_fence_client_wait(brw, fence, timeout);
239 }
240
241 static void
242 intel_dri_server_wait_sync(__DRIcontext *ctx, void *driver_fence, unsigned flags)
243 {
244 struct brw_context *brw = ctx->driverPrivate;
245 struct brw_fence *fence = driver_fence;
246
247 brw_fence_server_wait(brw, fence);
248 }
249
250 const __DRI2fenceExtension intelFenceExtension = {
251 .base = { __DRI2_FENCE, 1 },
252
253 .create_fence = intel_dri_create_fence,
254 .destroy_fence = intel_dri_destroy_fence,
255 .client_wait_sync = intel_dri_client_wait_sync,
256 .server_wait_sync = intel_dri_server_wait_sync,
257 .get_fence_from_cl_event = NULL,
258 };