9ee54a8c2a47659a59e44447de482a755d9c265b
[mesa.git] / src / intel / vulkan / anv_perf.c
1 /*
2 * Copyright © 2018 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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <stdint.h>
27
28 #include "anv_private.h"
29
30 #include "perf/gen_perf.h"
31 #include "perf/gen_perf_mdapi.h"
32
33 struct gen_perf_config *
34 anv_get_perf(const struct gen_device_info *devinfo, int fd)
35 {
36 struct gen_perf_config *perf = gen_perf_new(NULL);
37
38 gen_perf_init_metrics(perf, devinfo, fd);
39
40 /* We need DRM_I915_PERF_PROP_HOLD_PREEMPTION support, only available in
41 * perf revision 2.
42 */
43 if (perf->i915_perf_version < 3)
44 goto err;
45
46 return perf;
47
48 err:
49 ralloc_free(perf);
50 return NULL;
51 }
52
53 void
54 anv_device_perf_init(struct anv_device *device)
55 {
56 device->perf_fd = -1;
57 }
58
59 static int
60 anv_device_perf_open(struct anv_device *device, uint64_t metric_id)
61 {
62 uint64_t properties[DRM_I915_PERF_PROP_MAX * 2];
63 struct drm_i915_perf_open_param param;
64 int p = 0, stream_fd;
65
66 properties[p++] = DRM_I915_PERF_PROP_SAMPLE_OA;
67 properties[p++] = true;
68
69 properties[p++] = DRM_I915_PERF_PROP_OA_METRICS_SET;
70 properties[p++] = metric_id;
71
72 properties[p++] = DRM_I915_PERF_PROP_OA_FORMAT;
73 properties[p++] = device->info.gen >= 8 ?
74 I915_OA_FORMAT_A32u40_A4u32_B8_C8 :
75 I915_OA_FORMAT_A45_B8_C8;
76
77 properties[p++] = DRM_I915_PERF_PROP_OA_EXPONENT;
78 properties[p++] = 31; /* slowest sampling period */
79
80 properties[p++] = DRM_I915_PERF_PROP_CTX_HANDLE;
81 properties[p++] = device->context_id;
82
83 properties[p++] = DRM_I915_PERF_PROP_HOLD_PREEMPTION;
84 properties[p++] = true;
85
86 /* If global SSEU is available, pin it to the default. This will ensure on
87 * Gen11 for instance we use the full EU array. Initially when perf was
88 * enabled we would use only half on Gen11 because of functional
89 * requirements.
90 */
91 if (device->physical->perf->i915_perf_version >= 4) {
92 properties[p++] = DRM_I915_PERF_PROP_GLOBAL_SSEU;
93 properties[p++] = (uintptr_t) &device->physical->perf->sseu;
94 }
95
96 memset(&param, 0, sizeof(param));
97 param.flags = 0;
98 param.flags |= I915_PERF_FLAG_FD_CLOEXEC | I915_PERF_FLAG_FD_NONBLOCK;
99 param.properties_ptr = (uintptr_t)properties;
100 param.num_properties = p / 2;
101
102 stream_fd = gen_ioctl(device->fd, DRM_IOCTL_I915_PERF_OPEN, &param);
103 return stream_fd;
104 }
105
106 VkResult anv_InitializePerformanceApiINTEL(
107 VkDevice _device,
108 const VkInitializePerformanceApiInfoINTEL* pInitializeInfo)
109 {
110 ANV_FROM_HANDLE(anv_device, device, _device);
111
112 if (!device->physical->perf)
113 return VK_ERROR_EXTENSION_NOT_PRESENT;
114
115 /* Not much to do here */
116 return VK_SUCCESS;
117 }
118
119 VkResult anv_GetPerformanceParameterINTEL(
120 VkDevice _device,
121 VkPerformanceParameterTypeINTEL parameter,
122 VkPerformanceValueINTEL* pValue)
123 {
124 ANV_FROM_HANDLE(anv_device, device, _device);
125
126 if (!device->physical->perf)
127 return VK_ERROR_EXTENSION_NOT_PRESENT;
128
129 VkResult result = VK_SUCCESS;
130 switch (parameter) {
131 case VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL:
132 pValue->type = VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL;
133 pValue->data.valueBool = VK_TRUE;
134 break;
135
136 case VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL:
137 pValue->type = VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL;
138 pValue->data.value32 = 25;
139 break;
140
141 default:
142 result = VK_ERROR_FEATURE_NOT_PRESENT;
143 break;
144 }
145
146 return result;
147 }
148
149 VkResult anv_CmdSetPerformanceMarkerINTEL(
150 VkCommandBuffer commandBuffer,
151 const VkPerformanceMarkerInfoINTEL* pMarkerInfo)
152 {
153 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
154
155 cmd_buffer->intel_perf_marker = pMarkerInfo->marker;
156
157 return VK_SUCCESS;
158 }
159
160 VkResult anv_AcquirePerformanceConfigurationINTEL(
161 VkDevice _device,
162 const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo,
163 VkPerformanceConfigurationINTEL* pConfiguration)
164 {
165 ANV_FROM_HANDLE(anv_device, device, _device);
166
167 struct gen_perf_registers *perf_config =
168 gen_perf_load_configuration(device->physical->perf, device->fd,
169 GEN_PERF_QUERY_GUID_MDAPI);
170 if (!perf_config)
171 return VK_INCOMPLETE;
172
173 int ret = gen_perf_store_configuration(device->physical->perf, device->fd,
174 perf_config, NULL /* guid */);
175 if (ret < 0) {
176 ralloc_free(perf_config);
177 return VK_INCOMPLETE;
178 }
179
180 *pConfiguration = (VkPerformanceConfigurationINTEL) (uint64_t) ret;
181
182 return VK_SUCCESS;
183 }
184
185 VkResult anv_ReleasePerformanceConfigurationINTEL(
186 VkDevice _device,
187 VkPerformanceConfigurationINTEL _configuration)
188 {
189 ANV_FROM_HANDLE(anv_device, device, _device);
190 uint64_t config = (uint64_t) _configuration;
191
192 gen_ioctl(device->fd, DRM_IOCTL_I915_PERF_REMOVE_CONFIG, &config);
193
194 return VK_SUCCESS;
195 }
196
197 VkResult anv_QueueSetPerformanceConfigurationINTEL(
198 VkQueue _queue,
199 VkPerformanceConfigurationINTEL _configuration)
200 {
201 ANV_FROM_HANDLE(anv_queue, queue, _queue);
202 struct anv_device *device = queue->device;
203 uint64_t configuration = (uint64_t) _configuration;
204
205 if (device->perf_fd < 0) {
206 device->perf_fd = anv_device_perf_open(device, configuration);
207 if (device->perf_fd < 0)
208 return VK_ERROR_INITIALIZATION_FAILED;
209 } else {
210 int ret = gen_ioctl(device->perf_fd, I915_PERF_IOCTL_CONFIG,
211 (void *)(uintptr_t) _configuration);
212 if (ret < 0)
213 return anv_device_set_lost(device, "i915-perf config failed: %m");
214 }
215
216 return VK_SUCCESS;
217 }
218
219 void anv_UninitializePerformanceApiINTEL(
220 VkDevice _device)
221 {
222 ANV_FROM_HANDLE(anv_device, device, _device);
223
224 if (device->perf_fd >= 0) {
225 close(device->perf_fd);
226 device->perf_fd = -1;
227 }
228 }