+++ /dev/null
-/*
- * Copyright © 2015 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 <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-#include <drm.h>
-#include <i915_drm.h>
-
-#include "anv_private.h"
-#include "anv_aub.h"
-
-struct anv_aub_writer {
- FILE *file;
- uint32_t offset;
- int gen;
-};
-
-static void
-aub_out(struct anv_aub_writer *writer, uint32_t data)
-{
- fwrite(&data, 1, 4, writer->file);
-}
-
-static void
-aub_out_data(struct anv_aub_writer *writer, const void *data, size_t size)
-{
- fwrite(data, 1, size, writer->file);
-}
-
-static struct anv_aub_writer *
-get_anv_aub_writer(struct anv_device *device)
-{
- struct anv_aub_writer *writer = device->aub_writer;
- int entry = 0x200003;
- int i;
- int gtt_size = 0x10000;
- const char *filename;
-
- if (geteuid() != getuid())
- return NULL;
-
- if (writer)
- return writer;
-
- writer = malloc(sizeof(*writer));
- if (writer == NULL)
- return NULL;
-
- filename = "intel.aub";
- writer->gen = device->info.gen;
- writer->file = fopen(filename, "w+");
- if (!writer->file) {
- free(writer);
- return NULL;
- }
-
- /* Start allocating objects from just after the GTT. */
- writer->offset = gtt_size;
-
- /* Start with a (required) version packet. */
- aub_out(writer, CMD_AUB_HEADER | (13 - 2));
- aub_out(writer,
- (4 << AUB_HEADER_MAJOR_SHIFT) |
- (0 << AUB_HEADER_MINOR_SHIFT));
- for (i = 0; i < 8; i++) {
- aub_out(writer, 0); /* app name */
- }
- aub_out(writer, 0); /* timestamp */
- aub_out(writer, 0); /* timestamp */
- aub_out(writer, 0); /* comment len */
-
- /* Set up the GTT. The max we can handle is 256M */
- aub_out(writer, CMD_AUB_TRACE_HEADER_BLOCK | ((writer->gen >= 8 ? 6 : 5) - 2));
- aub_out(writer,
- AUB_TRACE_MEMTYPE_GTT_ENTRY |
- AUB_TRACE_TYPE_NOTYPE | AUB_TRACE_OP_DATA_WRITE);
- aub_out(writer, 0); /* subtype */
- aub_out(writer, 0); /* offset */
- aub_out(writer, gtt_size); /* size */
- if (writer->gen >= 8)
- aub_out(writer, 0);
- for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
- aub_out(writer, entry);
- }
-
- return device->aub_writer = writer;
-}
-
-void
-anv_aub_writer_destroy(struct anv_aub_writer *writer)
-{
- fclose(writer->file);
- free(writer);
-}
-
-
-/**
- * Break up large objects into multiple writes. Otherwise a 128kb VBO
- * would overflow the 16 bits of size field in the packet header and
- * everything goes badly after that.
- */
-static void
-aub_write_trace_block(struct anv_aub_writer *writer, uint32_t type,
- void *virtual, uint32_t size, uint32_t gtt_offset)
-{
- uint32_t block_size;
- uint32_t offset;
- uint32_t subtype = 0;
- static const char null_block[8 * 4096];
-
- for (offset = 0; offset < size; offset += block_size) {
- block_size = size - offset;
-
- if (block_size > 8 * 4096)
- block_size = 8 * 4096;
-
- aub_out(writer,
- CMD_AUB_TRACE_HEADER_BLOCK |
- ((writer->gen >= 8 ? 6 : 5) - 2));
- aub_out(writer,
- AUB_TRACE_MEMTYPE_GTT |
- type | AUB_TRACE_OP_DATA_WRITE);
- aub_out(writer, subtype);
- aub_out(writer, gtt_offset + offset);
- aub_out(writer, align_u32(block_size, 4));
- if (writer->gen >= 8)
- aub_out(writer, 0);
-
- if (virtual)
- aub_out_data(writer, (char *) virtual + offset, block_size);
- else
- aub_out_data(writer, null_block, block_size);
-
- /* Pad to a multiple of 4 bytes. */
- aub_out_data(writer, null_block, -block_size & 3);
- }
-}
-
-/*
- * Make a ringbuffer on fly and dump it
- */
-static void
-aub_build_dump_ringbuffer(struct anv_aub_writer *writer,
- uint32_t batch_offset, uint32_t offset,
- int ring_flag)
-{
- uint32_t ringbuffer[4096];
- int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */
- int ring_count = 0;
-
- if (ring_flag == I915_EXEC_BSD)
- ring = AUB_TRACE_TYPE_RING_PRB1;
- else if (ring_flag == I915_EXEC_BLT)
- ring = AUB_TRACE_TYPE_RING_PRB2;
-
- /* Make a ring buffer to execute our batchbuffer. */
- memset(ringbuffer, 0, sizeof(ringbuffer));
- if (writer->gen >= 8) {
- ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2);
- ringbuffer[ring_count++] = batch_offset;
- ringbuffer[ring_count++] = 0;
- } else {
- ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
- ringbuffer[ring_count++] = batch_offset;
- }
-
- /* Write out the ring. This appears to trigger execution of
- * the ring in the simulator.
- */
- aub_out(writer,
- CMD_AUB_TRACE_HEADER_BLOCK |
- ((writer->gen >= 8 ? 6 : 5) - 2));
- aub_out(writer,
- AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
- aub_out(writer, 0); /* general/surface subtype */
- aub_out(writer, offset);
- aub_out(writer, ring_count * 4);
- if (writer->gen >= 8)
- aub_out(writer, 0);
-
- /* FIXME: Need some flush operations here? */
- aub_out_data(writer, ringbuffer, ring_count * 4);
-}
-
-struct aub_bo {
- uint32_t size;
- uint32_t offset;
- void *map;
- void *relocated;
-};
-
-static void
-relocate_bo(struct aub_bo *aub_bo,
- const struct drm_i915_gem_exec_object2 *gem_obj,
- struct aub_bo *aub_bos)
-{
- const struct drm_i915_gem_relocation_entry *relocs =
- (const struct drm_i915_gem_relocation_entry *) gem_obj->relocs_ptr;
- uint32_t *dw;
-
- aub_bo->relocated = malloc(aub_bo->size);
- memcpy(aub_bo->relocated, aub_bo->map, aub_bo->size);
- for (size_t i = 0; i < gem_obj->relocation_count; i++) {
- assert(relocs[i].offset < aub_bo->size);
- dw = aub_bo->relocated + relocs[i].offset;
- *dw = aub_bos[relocs[i].target_handle].offset + relocs[i].delta;
- }
-}
-
-void
-anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_device *device = cmd_buffer->device;
- struct anv_aub_writer *writer;
- struct anv_bo *bo;
- uint32_t ring_flag = 0;
- uint32_t offset;
- struct aub_bo *aub_bos;
-
- writer = get_anv_aub_writer(device);
- if (writer == NULL)
- return;
-
- aub_bos = malloc(cmd_buffer->execbuf2.bo_count * sizeof(aub_bos[0]));
- offset = writer->offset;
- for (uint32_t i = 0; i < cmd_buffer->execbuf2.bo_count; i++) {
- bo = cmd_buffer->execbuf2.bos[i];
- if (bo->map)
- aub_bos[i].map = bo->map;
- else
- aub_bos[i].map = anv_gem_mmap(device, bo->gem_handle, 0, bo->size);
- aub_bos[i].size = bo->size;
- aub_bos[i].relocated = aub_bos[i].map;
- aub_bos[i].offset = offset;
- offset = align_u32(offset + bo->size + 4095, 4096);
- }
-
- for (uint32_t i = 0; i < cmd_buffer->execbuf2.bo_count; i++)
- relocate_bo(&aub_bos[i], &cmd_buffer->execbuf2.objects[i], aub_bos);
-
- struct aub_bo *batch_bo = &aub_bos[cmd_buffer->execbuf2.bo_count - 1];
-
- for (uint32_t i = 0; i < cmd_buffer->execbuf2.bo_count; i++) {
- bo = cmd_buffer->execbuf2.bos[i];
- if (&aub_bos[i] == batch_bo) {
- aub_write_trace_block(writer, AUB_TRACE_TYPE_BATCH,
- aub_bos[i].relocated,
- bo->size, aub_bos[i].offset);
- } else {
- aub_write_trace_block(writer, AUB_TRACE_TYPE_NOTYPE,
- aub_bos[i].relocated,
- bo->size, aub_bos[i].offset);
- }
- if (aub_bos[i].relocated != aub_bos[i].map)
- free(aub_bos[i].relocated);
- if (aub_bos[i].map != bo->map)
- anv_gem_munmap(aub_bos[i].map, bo->size);
- }
-
- /* Dump ring buffer */
- aub_build_dump_ringbuffer(writer, batch_bo->offset, offset, ring_flag);
-
- free(aub_bos);
-
- fflush(writer->file);
-}
#include "mesa/main/git_sha1.h"
#include "util/strtod.h"
-static int
-anv_env_get_int(const char *name)
-{
- const char *val = getenv(name);
-
- if (!val)
- return 0;
-
- return strtol(val, NULL, 0);
-}
-
static VkResult
anv_physical_device_init(struct anv_physical_device *device,
struct anv_instance *instance,
device->instance = instance;
device->path = path;
- device->chipset_id = anv_env_get_int("INTEL_DEVID_OVERRIDE");
- device->no_hw = false;
- if (device->chipset_id) {
- /* INTEL_DEVID_OVERRIDE implies INTEL_NO_HW. */
- device->no_hw = true;
- } else {
- device->chipset_id = anv_gem_get_param(fd, I915_PARAM_CHIPSET_ID);
- }
+ device->chipset_id = anv_gem_get_param(fd, I915_PARAM_CHIPSET_ID);
if (!device->chipset_id)
goto fail;
return anv_lookup_entrypoint(pName);
}
-static void
-parse_debug_flags(struct anv_device *device)
-{
- const char *debug, *p, *end;
-
- debug = getenv("INTEL_DEBUG");
- device->dump_aub = false;
- if (debug) {
- for (p = debug; *p; p = end + 1) {
- end = strchrnul(p, ',');
- if (end - p == 3 && memcmp(p, "aub", 3) == 0)
- device->dump_aub = true;
- if (end - p == 5 && memcmp(p, "no_hw", 5) == 0)
- device->no_hw = true;
- if (*end == '\0')
- break;
- }
- }
-}
-
static VkResult
anv_queue_init(struct anv_device *device, struct anv_queue *queue)
{
if (!device)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
- device->no_hw = physical_device->no_hw;
- parse_debug_flags(device);
-
device->instance = physical_device->instance;
/* XXX(chadv): Can we dup() physicalDevice->fd here? */
device->info = *physical_device->info;
device->compiler = anv_compiler_create(device);
- device->aub_writer = NULL;
pthread_mutex_init(&device->mutex, NULL);
close(device->fd);
- if (device->aub_writer)
- anv_aub_writer_destroy(device->aub_writer);
-
anv_instance_free(device->instance, device);
return VK_SUCCESS;
assert(cmd_buffer->level == VK_CMD_BUFFER_LEVEL_PRIMARY);
- if (device->dump_aub)
- anv_cmd_buffer_dump(cmd_buffer);
+ ret = anv_gem_execbuffer(device, &cmd_buffer->execbuf2.execbuf);
+ if (ret != 0)
+ return vk_error(VK_ERROR_UNKNOWN);
- if (!device->no_hw) {
- ret = anv_gem_execbuffer(device, &cmd_buffer->execbuf2.execbuf);
+ if (fence) {
+ ret = anv_gem_execbuffer(device, &fence->execbuf);
if (ret != 0)
return vk_error(VK_ERROR_UNKNOWN);
-
- if (fence) {
- ret = anv_gem_execbuffer(device, &fence->execbuf);
- if (ret != 0)
- return vk_error(VK_ERROR_UNKNOWN);
- }
-
- for (uint32_t i = 0; i < cmd_buffer->execbuf2.bo_count; i++)
- cmd_buffer->execbuf2.bos[i]->offset = cmd_buffer->execbuf2.objects[i].offset;
- } else {
- *(uint32_t *)queue->completed_serial.map = cmd_buffer->serial;
}
+
+ for (uint32_t i = 0; i < cmd_buffer->execbuf2.bo_count; i++)
+ cmd_buffer->execbuf2.bos[i]->offset = cmd_buffer->execbuf2.objects[i].offset;
}
return VK_SUCCESS;
execbuf.rsvd1 = device->context_id;
execbuf.rsvd2 = 0;
- if (!device->no_hw) {
- ret = anv_gem_execbuffer(device, &execbuf);
- if (ret != 0) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
+ ret = anv_gem_execbuffer(device, &execbuf);
+ if (ret != 0) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
+ }
- timeout = INT64_MAX;
- ret = anv_gem_wait(device, bo->gem_handle, &timeout);
- if (ret != 0) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
+ timeout = INT64_MAX;
+ ret = anv_gem_wait(device, bo->gem_handle, &timeout);
+ if (ret != 0) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
}
anv_state_pool_free(&device->dynamic_state_pool, state);