blob: 0770002f2162946dc9966feeee58b126131c8870 [file] [log] [blame]
Chia-I Wu214dac62014-08-05 11:07:40 +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
25#include <stdio.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <unistd.h>
30
31#include "genhw/genhw.h"
Chia-I Wude2bb862014-08-19 14:32:47 +080032#include "dispatch.h"
Chia-I Wuec841722014-08-25 22:36:01 +080033#include "queue.h"
Chia-I Wu214dac62014-08-05 11:07:40 +080034#include "gpu.h"
35
36static const char *gpu_get_name(const struct intel_gpu *gpu)
37{
38 const char *name = NULL;
39
40 if (gen_is_hsw(gpu->devid)) {
41 if (gen_is_desktop(gpu->devid))
42 name = "Intel(R) Haswell Desktop";
43 else if (gen_is_mobile(gpu->devid))
44 name = "Intel(R) Haswell Mobile";
45 else if (gen_is_server(gpu->devid))
46 name = "Intel(R) Haswell Server";
47 }
48 else if (gen_is_ivb(gpu->devid)) {
49 if (gen_is_desktop(gpu->devid))
50 name = "Intel(R) Ivybridge Desktop";
51 else if (gen_is_mobile(gpu->devid))
52 name = "Intel(R) Ivybridge Mobile";
53 else if (gen_is_server(gpu->devid))
54 name = "Intel(R) Ivybridge Server";
55 }
56 else if (gen_is_snb(gpu->devid)) {
57 if (gen_is_desktop(gpu->devid))
58 name = "Intel(R) Sandybridge Desktop";
59 else if (gen_is_mobile(gpu->devid))
60 name = "Intel(R) Sandybridge Mobile";
61 else if (gen_is_server(gpu->devid))
62 name = "Intel(R) Sandybridge Server";
63 }
64
65 if (!name)
66 name = "Unknown Intel Chipset";
67
68 return name;
69}
70
71static int gpu_open_internal(struct intel_gpu *gpu)
72{
73 if (gpu->fd_internal < 0) {
74 gpu->fd_internal = open(gpu->path, O_RDWR);
75 if (gpu->fd_internal < 0) {
76 icd_log(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, NULL, 0,
77 0, "failed to open %s", gpu->path);
78 }
79 }
80
81 return gpu->fd_internal;
82}
83
84static void gpu_close_internal(struct intel_gpu *gpu)
85{
86 if (gpu->fd_internal >= 0) {
87 close(gpu->fd_internal);
88 gpu->fd_internal = -1;
89 }
90}
91
92static struct intel_gpu *gpu_create(int gen, int devid, const char *path)
93{
94 struct intel_gpu *gpu;
95 size_t path_len;
96
97 gpu = icd_alloc(sizeof(*gpu), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
98 if (!gpu)
99 return NULL;
100
101 memset(gpu, 0, sizeof(*gpu));
102
103 /* debug layer is always enabled for intel_gpu */
Chia-I Wu6a42c2a2014-08-19 14:36:47 +0800104 gpu->dispatch = intel_dispatch_get(true);
Chia-I Wu214dac62014-08-05 11:07:40 +0800105
106 gpu->devid = devid;
107
108 path_len = strlen(path);
109 gpu->path = icd_alloc(path_len + 1, 0, XGL_SYSTEM_ALLOC_INTERNAL);
110 if (!gpu->path) {
111 icd_free(gpu);
112 return NULL;
113 }
114 memcpy(gpu->path, path, path_len + 1);
115
116 gpu->gen_opaque = gen;
117
118 /* 8192 dwords */
Chia-I Wud6109bb2014-08-21 09:12:19 +0800119 gpu->max_batch_buffer_size = sizeof(uint32_t) * 8192;
120
121 /* the winsys is prepared for one reloc every two dwords, then minus 2 */
122 gpu->batch_buffer_reloc_count =
123 gpu->max_batch_buffer_size / sizeof(uint32_t) / 2 - 2;
Chia-I Wu214dac62014-08-05 11:07:40 +0800124
125 gpu->fd_internal = -1;
126 gpu->fd = -1;
127
128 return gpu;
129}
130
131static void gpu_destroy(struct intel_gpu *gpu)
132{
133 gpu_close_internal(gpu);
134 icd_free(gpu->path);
135 icd_free(gpu);
136}
137
138static struct intel_gpu *intel_gpus;
139
140/**
141 * Return true if \p gpu is a valid intel_gpu.
142 */
143bool intel_gpu_is_valid(const struct intel_gpu *gpu)
144{
145 const struct intel_gpu *iter = intel_gpus;
146
147 while (iter) {
148 if (iter == gpu)
149 return true;
150 iter = iter->next;
151 }
152
153 return false;
154}
155
156static int devid_to_gen(int devid)
157{
158 int gen;
159
160 if (gen_is_hsw(devid))
161 gen = INTEL_GEN(7.5);
162 else if (gen_is_ivb(devid))
163 gen = INTEL_GEN(7);
164 else if (gen_is_snb(devid))
165 gen = INTEL_GEN(6);
166 else
167 gen = -1;
168
169 return gen;
170}
171
172XGL_RESULT intel_gpu_add(int devid, const char *path,
173 struct intel_gpu **gpu_ret)
174{
175 const int gen = devid_to_gen(devid);
176 struct intel_gpu *gpu;
177
178 if (gen < 0) {
179 icd_log(XGL_DBG_MSG_WARNING, XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE,
180 0, 0, "unsupported device id 0x%04x", devid);
181 return XGL_ERROR_INITIALIZATION_FAILED;
182 }
183
184 gpu = gpu_create(gen, devid, path);
185 if (!gpu)
186 return XGL_ERROR_OUT_OF_MEMORY;
187
188 gpu->next = intel_gpus;
189 intel_gpus = gpu;
190
191 *gpu_ret = gpu;
192
193 return XGL_SUCCESS;
194}
195
196void intel_gpu_remove_all(void)
197{
198 struct intel_gpu *gpu = intel_gpus;
199
200 while (gpu) {
201 struct intel_gpu *next = gpu->next;
202
203 gpu_destroy(gpu);
204 gpu = next;
205 }
206
207 intel_gpus = NULL;
208}
209
210struct intel_gpu *intel_gpu_get_list(void)
211{
212 return intel_gpus;
213}
214
215void intel_gpu_get_props(const struct intel_gpu *gpu,
216 XGL_PHYSICAL_GPU_PROPERTIES *props)
217{
218 const char *name;
219 size_t name_len;
220
221 props->structSize = sizeof(*props);
222
223 props->apiVersion = INTEL_API_VERSION;
224 props->driverVersion = INTEL_DRIVER_VERSION;
225
226 props->vendorId = 0x8086;
227 props->deviceId = gpu->devid;
228
229 props->gpuType = XGL_GPU_TYPE_INTEGRATED;
230
231 /* copy GPU name */
232 name = gpu_get_name(gpu);
233 name_len = strlen(name);
234 if (name_len > sizeof(props->gpuName) - 1)
235 name_len = sizeof(props->gpuName) - 1;
236 memcpy(props->gpuName, name, name_len);
237 props->gpuName[name_len] = '\0';
238
Chia-I Wud6109bb2014-08-21 09:12:19 +0800239 props->maxMemRefsPerSubmission = gpu->batch_buffer_reloc_count;
Chia-I Wu214dac62014-08-05 11:07:40 +0800240
241 props->virtualMemPageSize = 4096;
242
243 /* no size limit, but no bounded buffer could exceed 2GB */
244 props->maxInlineMemoryUpdateSize = 2u << 30;
245
246 props->maxBoundDescriptorSets = 1;
247 props->maxThreadGroupSize = 512;
248
249 /* incremented every 80ns */
250 props->timestampFrequency = 1000 * 1000 * 1000 / 80;
251
252 props->multiColorAttachmentClears = false;
253}
254
255void intel_gpu_get_perf(const struct intel_gpu *gpu,
256 XGL_PHYSICAL_GPU_PERFORMANCE *perf)
257{
258 /* TODO */
259 perf->maxGpuClock = 1.0f;
260 perf->aluPerClock = 1.0f;
261 perf->texPerClock = 1.0f;
262 perf->primsPerClock = 1.0f;
263 perf->pixelsPerClock = 1.0f;
264}
265
266void intel_gpu_get_queue_props(const struct intel_gpu *gpu,
267 enum intel_gpu_engine_type engine,
268 XGL_PHYSICAL_GPU_QUEUE_PROPERTIES *props)
269{
270 props->structSize = sizeof(*props);
271
272 switch (engine) {
273 case INTEL_GPU_ENGINE_3D:
274 props->queueFlags = XGL_QUEUE_GRAPHICS_BIT | XGL_QUEUE_COMPUTE_BIT;
275 props->queueCount = 1;
Chia-I Wuec841722014-08-25 22:36:01 +0800276 props->maxAtomicCounters = INTEL_QUEUE_ATOMIC_COUNTER_COUNT;
Chia-I Wu214dac62014-08-05 11:07:40 +0800277 props->supportsTimestamps = true;
278 break;
279 default:
280 assert(!"unknown engine type");
281 return;
282 }
283}
284
285void intel_gpu_get_memory_props(const struct intel_gpu *gpu,
286 XGL_PHYSICAL_GPU_MEMORY_PROPERTIES *props)
287{
288 props->structSize = sizeof(*props);
289
290 props->supportsMigration = false;
291
292 /* no kernel support yet */
293 props->supportsVirtualMemoryRemapping = false;
294
Chia-I Wu54c0c4b2014-08-06 13:48:25 +0800295 /* no winsys support for DRM_I915_GEM_USERPTR yet */
296 props->supportsPinning = false;
Chia-I Wu214dac62014-08-05 11:07:40 +0800297}
298
299XGL_RESULT intel_gpu_open(struct intel_gpu *gpu)
300{
301 gpu->fd = gpu_open_internal(gpu);
302
303 return (gpu->fd >= 0) ? XGL_SUCCESS : XGL_ERROR_UNKNOWN;
304}
305
306void intel_gpu_close(struct intel_gpu *gpu)
307{
308 gpu->fd = -1;
309 gpu_close_internal(gpu);
310}
311
312bool intel_gpu_has_extension(const struct intel_gpu *gpu, const char *ext)
313{
314 return false;
315}
Chia-I Wubec90a02014-08-06 12:33:03 +0800316
317XGL_RESULT XGLAPI intelGetGpuInfo(
318 XGL_PHYSICAL_GPU gpu_,
319 XGL_PHYSICAL_GPU_INFO_TYPE infoType,
320 XGL_SIZE* pDataSize,
321 XGL_VOID* pData)
322{
323 const struct intel_gpu *gpu = intel_gpu(gpu_);
324 XGL_RESULT ret = XGL_SUCCESS;
325
326 switch (infoType) {
327 case XGL_INFO_TYPE_PHYSICAL_GPU_PROPERTIES:
328 if (pData == NULL) {
329 return XGL_ERROR_INVALID_POINTER;
330 }
331 *pDataSize = sizeof(XGL_PHYSICAL_GPU_PROPERTIES);
332 intel_gpu_get_props(gpu, pData);
333 break;
334
335 case XGL_INFO_TYPE_PHYSICAL_GPU_PERFORMANCE:
336 if (pData == NULL) {
337 return XGL_ERROR_INVALID_POINTER;
338 }
339 *pDataSize = sizeof(XGL_PHYSICAL_GPU_PERFORMANCE);
340 intel_gpu_get_perf(gpu, pData);
341 break;
342
343 case XGL_INFO_TYPE_PHYSICAL_GPU_QUEUE_PROPERTIES:
344 /*
345 * XGL Programmers guide, page 33:
346 * to determine the data size an application calls
347 * xglGetGpuInfo() with a NULL data pointer. The
348 * expected data size for all queue property structures
349 * is returned in pDataSize
350 */
351 *pDataSize = sizeof(XGL_PHYSICAL_GPU_QUEUE_PROPERTIES) *
352 INTEL_GPU_ENGINE_COUNT;
353 if (pData != NULL) {
354 XGL_PHYSICAL_GPU_QUEUE_PROPERTIES *dst = pData;
355 int engine;
356
357 for (engine = 0; engine < INTEL_GPU_ENGINE_COUNT; engine++) {
358 intel_gpu_get_queue_props(gpu, engine, dst);
359 dst++;
360 }
361 }
362 break;
363
364 case XGL_INFO_TYPE_PHYSICAL_GPU_MEMORY_PROPERTIES:
365 if (pData == NULL) {
366 return XGL_ERROR_INVALID_POINTER;
367 }
368 *pDataSize = sizeof(XGL_PHYSICAL_GPU_MEMORY_PROPERTIES);
369 intel_gpu_get_memory_props(gpu, pData);
370 break;
371
372 default:
373 ret = XGL_ERROR_INVALID_VALUE;
374 }
375
376 return ret;
377}
378
379XGL_RESULT XGLAPI intelGetExtensionSupport(
380 XGL_PHYSICAL_GPU gpu_,
381 const XGL_CHAR* pExtName)
382{
383 struct intel_gpu *gpu = intel_gpu(gpu_);
384
385 return (intel_gpu_has_extension(gpu, (const char *) pExtName)) ?
386 XGL_SUCCESS : XGL_ERROR_INVALID_EXTENSION;
387}
Chia-I Wu251e7d92014-08-19 13:35:42 +0800388
389XGL_RESULT XGLAPI intelGetMultiGpuCompatibility(
390 XGL_PHYSICAL_GPU gpu0,
391 XGL_PHYSICAL_GPU gpu1,
392 XGL_GPU_COMPATIBILITY_INFO* pInfo)
393{
394 return XGL_ERROR_UNAVAILABLE;
395}