diff options
Diffstat (limited to 'src/intel/vulkan/anv_perf.c')
-rw-r--r-- | src/intel/vulkan/anv_perf.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/intel/vulkan/anv_perf.c b/src/intel/vulkan/anv_perf.c new file mode 100644 index 00000000000..6a9fb4f6f11 --- /dev/null +++ b/src/intel/vulkan/anv_perf.c @@ -0,0 +1,224 @@ +/* + * Copyright © 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> + +#include "anv_private.h" + +#include "perf/gen_perf.h" +#include "perf/gen_perf_mdapi.h" + +struct gen_perf_config * +anv_get_perf(const struct gen_device_info *devinfo, int fd) +{ + struct gen_perf_config *perf = gen_perf_new(NULL); + + gen_perf_init_metrics(perf, devinfo, fd); + + /* We need DRM_I915_PERF_PROP_HOLD_PREEMPTION support, only available in + * perf revision 2. + */ + if (anv_gem_get_param(fd, I915_PARAM_PERF_REVISION) < 3) + goto err; + + return perf; + + err: + ralloc_free(perf); + return NULL; +} + +void +anv_device_perf_init(struct anv_device *device) +{ + device->perf_fd = -1; +} + +static int +anv_device_perf_open(struct anv_device *device, uint64_t metric_id) +{ + uint64_t properties[DRM_I915_PERF_PROP_MAX * 2]; + struct drm_i915_perf_open_param param; + int p = 0, stream_fd; + + properties[p++] = DRM_I915_PERF_PROP_SAMPLE_OA; + properties[p++] = true; + + properties[p++] = DRM_I915_PERF_PROP_OA_METRICS_SET; + properties[p++] = metric_id; + + properties[p++] = DRM_I915_PERF_PROP_OA_FORMAT; + properties[p++] = device->info.gen >= 8 ? + I915_OA_FORMAT_A32u40_A4u32_B8_C8 : + I915_OA_FORMAT_A45_B8_C8; + + properties[p++] = DRM_I915_PERF_PROP_OA_EXPONENT; + properties[p++] = 31; /* slowest sampling period */ + + properties[p++] = DRM_I915_PERF_PROP_CTX_HANDLE; + properties[p++] = device->context_id; + + properties[p++] = DRM_I915_PERF_PROP_HOLD_PREEMPTION; + properties[p++] = true; + + memset(¶m, 0, sizeof(param)); + param.flags = 0; + param.flags |= I915_PERF_FLAG_FD_CLOEXEC | I915_PERF_FLAG_FD_NONBLOCK; + param.properties_ptr = (uintptr_t)properties; + param.num_properties = p / 2; + + stream_fd = gen_ioctl(device->fd, DRM_IOCTL_I915_PERF_OPEN, ¶m); + return stream_fd; +} + +VkResult anv_InitializePerformanceApiINTEL( + VkDevice _device, + const VkInitializePerformanceApiInfoINTEL* pInitializeInfo) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + const struct anv_physical_device *pdevice = &device->instance->physicalDevice; + + if (!pdevice->perf) + return VK_ERROR_EXTENSION_NOT_PRESENT; + + /* Not much to do here */ + return VK_SUCCESS; +} + +VkResult anv_GetPerformanceParameterINTEL( + VkDevice _device, + VkPerformanceParameterTypeINTEL parameter, + VkPerformanceValueINTEL* pValue) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + const struct anv_physical_device *pdevice = &device->instance->physicalDevice; + + if (!pdevice->perf) + return VK_ERROR_EXTENSION_NOT_PRESENT; + + VkResult result = VK_SUCCESS; + switch (parameter) { + case VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL: + pValue->type = VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL; + pValue->data.valueBool = VK_TRUE; + break; + + case VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL: + pValue->type = VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL; + pValue->data.value32 = 25; + break; + + default: + result = VK_ERROR_FEATURE_NOT_PRESENT; + break; + } + + return result; +} + +VkResult anv_CmdSetPerformanceMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceMarkerInfoINTEL* pMarkerInfo) +{ + ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + + cmd_buffer->intel_perf_marker = pMarkerInfo->marker; + + return VK_SUCCESS; +} + +VkResult anv_AcquirePerformanceConfigurationINTEL( + VkDevice _device, + const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, + VkPerformanceConfigurationINTEL* pConfiguration) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + const struct anv_physical_device *pdevice = &device->instance->physicalDevice; + + struct gen_perf_registers *perf_config = + gen_perf_load_configuration(pdevice->perf, device->fd, + GEN_PERF_QUERY_GUID_MDAPI); + if (!perf_config) + return VK_INCOMPLETE; + + int ret = gen_perf_store_configuration(pdevice->perf, device->fd, + perf_config, NULL /* guid */); + if (ret < 0) { + ralloc_free(perf_config); + return VK_INCOMPLETE; + } + + *pConfiguration = (VkPerformanceConfigurationINTEL) (uint64_t) ret; + + return VK_SUCCESS; +} + +VkResult anv_ReleasePerformanceConfigurationINTEL( + VkDevice _device, + VkPerformanceConfigurationINTEL _configuration) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + uint64_t config = (uint64_t) _configuration; + + gen_ioctl(device->fd, DRM_IOCTL_I915_PERF_REMOVE_CONFIG, &config); + + return VK_SUCCESS; +} + +VkResult anv_QueueSetPerformanceConfigurationINTEL( + VkQueue _queue, + VkPerformanceConfigurationINTEL _configuration) +{ + ANV_FROM_HANDLE(anv_queue, queue, _queue); + struct anv_device *device = queue->device; + uint64_t configuration = (uint64_t) _configuration; + + if (device->perf_fd < 0) { + device->perf_fd = anv_device_perf_open(device, configuration); + if (device->perf_fd < 0) + return VK_ERROR_INITIALIZATION_FAILED; + } else { + int ret = gen_ioctl(device->perf_fd, I915_PERF_IOCTL_CONFIG, + (void *)(uintptr_t) _configuration); + if (ret < 0) { + return anv_device_set_lost(device, + "i915-perf config failed: %s", + strerror(ret)); + } + } + + return VK_SUCCESS; +} + +void anv_UninitializePerformanceApiINTEL( + VkDevice _device) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + if (device->perf_fd >= 0) { + close(device->perf_fd); + device->perf_fd = -1; + } +} |