2018-06-07 18:02:03 +01:00
|
|
|
/*
|
|
|
|
* 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);
|
2019-10-24 13:04:51 +01:00
|
|
|
if (ret < 0)
|
|
|
|
return anv_device_set_lost(device, "i915-perf config failed: %m");
|
2018-06-07 18:02:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|