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