2017-11-23 23:15:14 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2017 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
2018-08-19 00:31:46 -07:00
|
|
|
* 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:
|
2017-11-23 23:15:14 -08:00
|
|
|
*
|
2018-08-19 00:31:46 -07:00
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
|
* in all copies or substantial portions of the Software.
|
2017-11-23 23:15:14 -08:00
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
2018-08-19 00:31:46 -07:00
|
|
|
* 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.
|
2017-11-23 23:15:14 -08:00
|
|
|
*/
|
|
|
|
|
|
2018-07-30 23:49:34 -07:00
|
|
|
/**
|
|
|
|
|
* @file iris_batch.c
|
|
|
|
|
*
|
|
|
|
|
* Batchbuffer and command submission module.
|
|
|
|
|
*
|
|
|
|
|
* Every API draw call results in a number of GPU commands, which we
|
|
|
|
|
* collect into a "batch buffer". Typically, many draw calls are grouped
|
|
|
|
|
* into a single batch to amortize command submission overhead.
|
|
|
|
|
*
|
|
|
|
|
* We submit batches to the kernel using the I915_GEM_EXECBUFFER2 ioctl.
|
|
|
|
|
* One critical piece of data is the "validation list", which contains a
|
|
|
|
|
* list of the buffer objects (BOs) which the commands in the GPU need.
|
|
|
|
|
* The kernel will make sure these are resident and pinned at the correct
|
|
|
|
|
* virtual memory address before executing our batch. If a BO is not in
|
|
|
|
|
* the validation list, it effectively does not exist, so take care.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "iris_batch.h"
|
|
|
|
|
#include "iris_bufmgr.h"
|
|
|
|
|
#include "iris_context.h"
|
2018-11-09 15:02:12 +00:00
|
|
|
#include "iris_fence.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
|
|
|
|
|
#include "drm-uapi/i915_drm.h"
|
|
|
|
|
|
2021-03-03 13:20:06 -08:00
|
|
|
#include "common/intel_aux_map.h"
|
|
|
|
|
#include "intel/common/intel_gem.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "util/hash_table.h"
|
2018-04-20 23:28:03 -07:00
|
|
|
#include "util/set.h"
|
2020-02-18 22:22:51 +00:00
|
|
|
#include "util/u_upload_mgr.h"
|
2017-11-23 23:15:14 -08:00
|
|
|
#include "main/macros.h"
|
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <xf86drm.h>
|
|
|
|
|
|
2018-11-21 11:12:11 +00:00
|
|
|
#if HAVE_VALGRIND
|
|
|
|
|
#include <valgrind.h>
|
|
|
|
|
#include <memcheck.h>
|
|
|
|
|
#define VG(x) x
|
|
|
|
|
#else
|
|
|
|
|
#define VG(x)
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
#define FILE_DEBUG_FLAG DEBUG_BUFMGR
|
|
|
|
|
|
2017-12-27 02:25:20 -08:00
|
|
|
static void
|
|
|
|
|
iris_batch_reset(struct iris_batch *batch);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-11-08 14:42:00 -08:00
|
|
|
static unsigned
|
|
|
|
|
num_fences(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
return util_dynarray_num_elements(&batch->exec_fences,
|
|
|
|
|
struct drm_i915_gem_exec_fence);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Debugging code to dump the fence list, used by INTEL_DEBUG=submit.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
dump_fence_list(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Fence list (length %u): ", num_fences(batch));
|
|
|
|
|
|
|
|
|
|
util_dynarray_foreach(&batch->exec_fences,
|
|
|
|
|
struct drm_i915_gem_exec_fence, f) {
|
|
|
|
|
fprintf(stderr, "%s%u%s ",
|
|
|
|
|
(f->flags & I915_EXEC_FENCE_WAIT) ? "..." : "",
|
|
|
|
|
f->handle,
|
|
|
|
|
(f->flags & I915_EXEC_FENCE_SIGNAL) ? "!" : "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 23:49:34 -07:00
|
|
|
/**
|
|
|
|
|
* Debugging code to dump the validation list, used by INTEL_DEBUG=submit.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2017-12-27 02:25:20 -08:00
|
|
|
dump_validation_list(struct iris_batch *batch)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
2017-12-27 02:25:20 -08:00
|
|
|
fprintf(stderr, "Validation list (length %d):\n", batch->exec_count);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2017-12-27 02:25:20 -08:00
|
|
|
for (int i = 0; i < batch->exec_count; i++) {
|
2018-04-06 22:39:01 -07:00
|
|
|
uint64_t flags = batch->validation_list[i].flags;
|
2017-12-27 02:25:20 -08:00
|
|
|
assert(batch->validation_list[i].handle ==
|
|
|
|
|
batch->exec_bos[i]->gem_handle);
|
2020-01-24 23:45:40 +01:00
|
|
|
fprintf(stderr, "[%2d]: %2d %-14s @ 0x%"PRIx64" (%"PRIu64"B)\t %2d refs %s\n",
|
2018-04-06 22:39:01 -07:00
|
|
|
i,
|
2017-12-27 02:25:20 -08:00
|
|
|
batch->validation_list[i].handle,
|
|
|
|
|
batch->exec_bos[i]->name,
|
2020-01-24 23:45:40 +01:00
|
|
|
(uint64_t)batch->validation_list[i].offset,
|
2018-06-18 00:39:10 -07:00
|
|
|
batch->exec_bos[i]->size,
|
2018-12-08 11:21:48 -08:00
|
|
|
batch->exec_bos[i]->refcount,
|
|
|
|
|
(flags & EXEC_OBJECT_WRITE) ? " (write)" : "");
|
2017-12-27 02:25:20 -08:00
|
|
|
}
|
|
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-07-30 23:49:34 -07:00
|
|
|
/**
|
|
|
|
|
* Return BO information to the batch decoder (for debugging).
|
|
|
|
|
*/
|
2018-04-06 16:21:21 -07:00
|
|
|
static struct gen_batch_decode_bo
|
2019-03-07 16:59:53 +00:00
|
|
|
decode_get_bo(void *v_batch, bool ppgtt, uint64_t address)
|
2018-04-06 16:21:21 -07:00
|
|
|
{
|
|
|
|
|
struct iris_batch *batch = v_batch;
|
|
|
|
|
|
2019-03-07 16:59:53 +00:00
|
|
|
assert(ppgtt);
|
|
|
|
|
|
2018-04-06 16:21:21 -07:00
|
|
|
for (int i = 0; i < batch->exec_count; i++) {
|
2018-04-06 17:01:45 -07:00
|
|
|
struct iris_bo *bo = batch->exec_bos[i];
|
2018-04-07 06:59:22 -07:00
|
|
|
/* The decoder zeroes out the top 16 bits, so we need to as well */
|
|
|
|
|
uint64_t bo_address = bo->gtt_offset & (~0ull >> 16);
|
|
|
|
|
|
|
|
|
|
if (address >= bo_address && address < bo_address + bo->size) {
|
2018-04-06 16:21:21 -07:00
|
|
|
return (struct gen_batch_decode_bo) {
|
|
|
|
|
.addr = address,
|
2018-04-06 17:01:45 -07:00
|
|
|
.size = bo->size,
|
|
|
|
|
.map = iris_bo_map(batch->dbg, bo, MAP_READ) +
|
2018-04-07 06:59:22 -07:00
|
|
|
(address - bo_address),
|
2018-04-06 16:21:21 -07:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (struct gen_batch_decode_bo) { };
|
|
|
|
|
}
|
|
|
|
|
|
iris: Record state sizes for INTEL_DEBUG=bat decoding.
Felix noticed a crash when using INTEL_DEBUG=bat decoding. It turned
out that we were sometimes placing variable length data near the end
of a buffer, and with the decoder guessing random lengths rather than
having an actual count, it was walking off the end and crashing. So
this does more than improve the decoder output.
Unfortunately, this is a bit more complicated than i965's handling,
because we don't have a single state buffer. Various places upload
data via u_upload_mgr, and so there isn't a central place to record
the size. We don't need to catch every single place, however, since
it's only important to record variable length packets (like viewports
and binding tables).
State data also lives arbitrarily long, rather than being discarded on
every batch like i965, so we don't know when to clear out old entries
either. (We also don't have a callback when an upload buffer is
released.) So, this tracking may space leak over time. That's probably
okay though, as this is only a debugging feature and it's a slow leak.
We may also get lucky and overwrite existing entries as we reuse BOs,
though I find this unlikely to happen.
The fact that the decoder works in terms of offsets from a state base
address is also not ideal, as dynamic state base address and surface
state base address differ for iris. However, because dynamic state
addresses start from the top of a 4GB region, and binding tables start
from addresses [0, 64K), it's highly unlikely that we'll get overlap.
We can always improve this, but for now it's better than what we had.
2019-05-22 18:14:38 -07:00
|
|
|
static unsigned
|
2019-10-02 15:09:33 -04:00
|
|
|
decode_get_state_size(void *v_batch,
|
|
|
|
|
uint64_t address,
|
|
|
|
|
UNUSED uint64_t base_address)
|
iris: Record state sizes for INTEL_DEBUG=bat decoding.
Felix noticed a crash when using INTEL_DEBUG=bat decoding. It turned
out that we were sometimes placing variable length data near the end
of a buffer, and with the decoder guessing random lengths rather than
having an actual count, it was walking off the end and crashing. So
this does more than improve the decoder output.
Unfortunately, this is a bit more complicated than i965's handling,
because we don't have a single state buffer. Various places upload
data via u_upload_mgr, and so there isn't a central place to record
the size. We don't need to catch every single place, however, since
it's only important to record variable length packets (like viewports
and binding tables).
State data also lives arbitrarily long, rather than being discarded on
every batch like i965, so we don't know when to clear out old entries
either. (We also don't have a callback when an upload buffer is
released.) So, this tracking may space leak over time. That's probably
okay though, as this is only a debugging feature and it's a slow leak.
We may also get lucky and overwrite existing entries as we reuse BOs,
though I find this unlikely to happen.
The fact that the decoder works in terms of offsets from a state base
address is also not ideal, as dynamic state base address and surface
state base address differ for iris. However, because dynamic state
addresses start from the top of a 4GB region, and binding tables start
from addresses [0, 64K), it's highly unlikely that we'll get overlap.
We can always improve this, but for now it's better than what we had.
2019-05-22 18:14:38 -07:00
|
|
|
{
|
|
|
|
|
struct iris_batch *batch = v_batch;
|
|
|
|
|
unsigned size = (uintptr_t)
|
2019-10-02 15:09:33 -04:00
|
|
|
_mesa_hash_table_u64_search(batch->state_sizes, address);
|
iris: Record state sizes for INTEL_DEBUG=bat decoding.
Felix noticed a crash when using INTEL_DEBUG=bat decoding. It turned
out that we were sometimes placing variable length data near the end
of a buffer, and with the decoder guessing random lengths rather than
having an actual count, it was walking off the end and crashing. So
this does more than improve the decoder output.
Unfortunately, this is a bit more complicated than i965's handling,
because we don't have a single state buffer. Various places upload
data via u_upload_mgr, and so there isn't a central place to record
the size. We don't need to catch every single place, however, since
it's only important to record variable length packets (like viewports
and binding tables).
State data also lives arbitrarily long, rather than being discarded on
every batch like i965, so we don't know when to clear out old entries
either. (We also don't have a callback when an upload buffer is
released.) So, this tracking may space leak over time. That's probably
okay though, as this is only a debugging feature and it's a slow leak.
We may also get lucky and overwrite existing entries as we reuse BOs,
though I find this unlikely to happen.
The fact that the decoder works in terms of offsets from a state base
address is also not ideal, as dynamic state base address and surface
state base address differ for iris. However, because dynamic state
addresses start from the top of a 4GB region, and binding tables start
from addresses [0, 64K), it's highly unlikely that we'll get overlap.
We can always improve this, but for now it's better than what we had.
2019-05-22 18:14:38 -07:00
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 23:49:34 -07:00
|
|
|
/**
|
|
|
|
|
* Decode the current batch.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
decode_batch(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
void *map = iris_bo_map(batch->dbg, batch->exec_bos[0], MAP_READ);
|
|
|
|
|
gen_print_batch(&batch->decoder, map, batch->primary_batch_size,
|
2019-03-07 16:14:13 +00:00
|
|
|
batch->exec_bos[0]->gtt_offset, false);
|
2018-07-30 23:49:34 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
void
|
2020-05-01 10:17:15 -07:00
|
|
|
iris_init_batch(struct iris_context *ice,
|
2018-11-20 09:00:22 -08:00
|
|
|
enum iris_batch_name name,
|
2019-02-22 23:31:56 +00:00
|
|
|
int priority)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
2020-05-01 10:17:15 -07:00
|
|
|
struct iris_batch *batch = &ice->batches[name];
|
|
|
|
|
struct iris_screen *screen = (void *) ice->ctx.screen;
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
batch->screen = screen;
|
2020-05-01 10:17:15 -07:00
|
|
|
batch->dbg = &ice->dbg;
|
|
|
|
|
batch->reset = &ice->reset;
|
|
|
|
|
batch->state_sizes = ice->state.sizes;
|
2018-11-08 15:32:59 -08:00
|
|
|
batch->name = name;
|
2020-10-28 14:13:48 -07:00
|
|
|
batch->ice = ice;
|
2021-02-14 20:28:02 +02:00
|
|
|
batch->contains_fence_signal = false;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2020-05-27 22:19:52 +01:00
|
|
|
batch->fine_fences.uploader =
|
2020-02-18 22:22:51 +00:00
|
|
|
u_upload_create(&ice->ctx, 4096, PIPE_BIND_CUSTOM,
|
|
|
|
|
PIPE_USAGE_STAGING, 0);
|
2020-05-27 22:19:52 +01:00
|
|
|
iris_fine_fence_init(batch);
|
2020-02-18 22:22:51 +00:00
|
|
|
|
2018-11-07 09:35:19 -08:00
|
|
|
batch->hw_ctx_id = iris_create_hw_context(screen->bufmgr);
|
|
|
|
|
assert(batch->hw_ctx_id);
|
|
|
|
|
|
2019-02-22 23:31:56 +00:00
|
|
|
iris_hw_context_set_priority(screen->bufmgr, batch->hw_ctx_id, priority);
|
|
|
|
|
|
2018-11-08 14:42:00 -08:00
|
|
|
util_dynarray_init(&batch->exec_fences, ralloc_context(NULL));
|
2020-04-28 23:24:38 -07:00
|
|
|
util_dynarray_init(&batch->syncobjs, ralloc_context(NULL));
|
2018-11-08 14:42:00 -08:00
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
batch->exec_count = 0;
|
|
|
|
|
batch->exec_array_size = 100;
|
|
|
|
|
batch->exec_bos =
|
|
|
|
|
malloc(batch->exec_array_size * sizeof(batch->exec_bos[0]));
|
|
|
|
|
batch->validation_list =
|
|
|
|
|
malloc(batch->exec_array_size * sizeof(batch->validation_list[0]));
|
|
|
|
|
|
2018-04-20 23:28:03 -07:00
|
|
|
batch->cache.render = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
|
|
|
|
|
_mesa_key_pointer_equal);
|
2018-11-06 21:12:30 -08:00
|
|
|
|
|
|
|
|
memset(batch->other_batches, 0, sizeof(batch->other_batches));
|
|
|
|
|
|
|
|
|
|
for (int i = 0, j = 0; i < IRIS_BATCH_COUNT; i++) {
|
2020-05-01 10:17:15 -07:00
|
|
|
if (i != name)
|
|
|
|
|
batch->other_batches[j++] = &ice->batches[i];
|
2018-11-06 21:12:30 -08:00
|
|
|
}
|
|
|
|
|
|
2020-09-14 18:49:43 +02:00
|
|
|
if (INTEL_DEBUG) {
|
2018-04-06 16:21:21 -07:00
|
|
|
const unsigned decode_flags =
|
|
|
|
|
GEN_BATCH_DECODE_FULL |
|
|
|
|
|
((INTEL_DEBUG & DEBUG_COLOR) ? GEN_BATCH_DECODE_IN_COLOR : 0) |
|
2018-04-06 17:01:45 -07:00
|
|
|
GEN_BATCH_DECODE_OFFSETS |
|
2018-04-06 16:21:21 -07:00
|
|
|
GEN_BATCH_DECODE_FLOATS;
|
|
|
|
|
|
|
|
|
|
gen_batch_decode_ctx_init(&batch->decoder, &screen->devinfo,
|
|
|
|
|
stderr, decode_flags, NULL,
|
iris: Record state sizes for INTEL_DEBUG=bat decoding.
Felix noticed a crash when using INTEL_DEBUG=bat decoding. It turned
out that we were sometimes placing variable length data near the end
of a buffer, and with the decoder guessing random lengths rather than
having an actual count, it was walking off the end and crashing. So
this does more than improve the decoder output.
Unfortunately, this is a bit more complicated than i965's handling,
because we don't have a single state buffer. Various places upload
data via u_upload_mgr, and so there isn't a central place to record
the size. We don't need to catch every single place, however, since
it's only important to record variable length packets (like viewports
and binding tables).
State data also lives arbitrarily long, rather than being discarded on
every batch like i965, so we don't know when to clear out old entries
either. (We also don't have a callback when an upload buffer is
released.) So, this tracking may space leak over time. That's probably
okay though, as this is only a debugging feature and it's a slow leak.
We may also get lucky and overwrite existing entries as we reuse BOs,
though I find this unlikely to happen.
The fact that the decoder works in terms of offsets from a state base
address is also not ideal, as dynamic state base address and surface
state base address differ for iris. However, because dynamic state
addresses start from the top of a 4GB region, and binding tables start
from addresses [0, 64K), it's highly unlikely that we'll get overlap.
We can always improve this, but for now it's better than what we had.
2019-05-22 18:14:38 -07:00
|
|
|
decode_get_bo, decode_get_state_size, batch);
|
2019-07-12 13:52:35 -07:00
|
|
|
batch->decoder.dynamic_base = IRIS_MEMZONE_DYNAMIC_START;
|
|
|
|
|
batch->decoder.instruction_base = IRIS_MEMZONE_SHADER_START;
|
2018-05-02 22:11:54 -07:00
|
|
|
batch->decoder.max_vbo_decoded_lines = 32;
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2020-10-27 15:56:06 -07:00
|
|
|
iris_init_batch_measure(ice, batch);
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
iris_batch_reset(batch);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-19 21:40:54 -08:00
|
|
|
static struct drm_i915_gem_exec_object2 *
|
|
|
|
|
find_validation_entry(struct iris_batch *batch, struct iris_bo *bo)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
|
|
|
|
unsigned index = READ_ONCE(bo->index);
|
|
|
|
|
|
|
|
|
|
if (index < batch->exec_count && batch->exec_bos[index] == bo)
|
2018-11-19 21:40:54 -08:00
|
|
|
return &batch->validation_list[index];
|
2017-11-23 23:15:14 -08:00
|
|
|
|
|
|
|
|
/* May have been shared between multiple active batches */
|
|
|
|
|
for (index = 0; index < batch->exec_count; index++) {
|
|
|
|
|
if (batch->exec_bos[index] == bo)
|
2018-11-19 21:40:54 -08:00
|
|
|
return &batch->validation_list[index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-28 01:56:59 -07:00
|
|
|
static void
|
|
|
|
|
ensure_exec_obj_space(struct iris_batch *batch, uint32_t count)
|
|
|
|
|
{
|
|
|
|
|
while (batch->exec_count + count > batch->exec_array_size) {
|
|
|
|
|
batch->exec_array_size *= 2;
|
|
|
|
|
batch->exec_bos =
|
|
|
|
|
realloc(batch->exec_bos,
|
|
|
|
|
batch->exec_array_size * sizeof(batch->exec_bos[0]));
|
|
|
|
|
batch->validation_list =
|
|
|
|
|
realloc(batch->validation_list,
|
|
|
|
|
batch->exec_array_size * sizeof(batch->validation_list[0]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-19 21:40:54 -08:00
|
|
|
/**
|
|
|
|
|
* Add a buffer to the current batch's validation list.
|
|
|
|
|
*
|
|
|
|
|
* You must call this on any BO you wish to use in this batch, to ensure
|
|
|
|
|
* that it's resident when the GPU commands execute.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
iris_use_pinned_bo(struct iris_batch *batch,
|
|
|
|
|
struct iris_bo *bo,
|
2020-05-29 16:38:43 -07:00
|
|
|
bool writable, enum iris_domain access)
|
2018-11-19 21:40:54 -08:00
|
|
|
{
|
|
|
|
|
assert(bo->kflags & EXEC_OBJECT_PINNED);
|
|
|
|
|
|
2018-11-19 22:08:51 -08:00
|
|
|
/* Never mark the workaround BO with EXEC_OBJECT_WRITE. We don't care
|
|
|
|
|
* about the order of any writes to that buffer, and marking it writable
|
|
|
|
|
* would introduce data dependencies between multiple batches which share
|
|
|
|
|
* the buffer.
|
|
|
|
|
*/
|
|
|
|
|
if (bo == batch->screen->workaround_bo)
|
|
|
|
|
writable = false;
|
|
|
|
|
|
2020-05-29 16:38:43 -07:00
|
|
|
if (access < NUM_IRIS_DOMAINS) {
|
|
|
|
|
assert(batch->sync_region_depth);
|
|
|
|
|
iris_bo_bump_seqno(bo, batch->next_seqno, access);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-19 21:40:54 -08:00
|
|
|
struct drm_i915_gem_exec_object2 *existing_entry =
|
|
|
|
|
find_validation_entry(batch, bo);
|
|
|
|
|
|
|
|
|
|
if (existing_entry) {
|
|
|
|
|
/* The BO is already in the validation list; mark it writable */
|
|
|
|
|
if (writable)
|
|
|
|
|
existing_entry->flags |= EXEC_OBJECT_WRITE;
|
|
|
|
|
|
|
|
|
|
return;
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2020-10-27 15:56:06 -07:00
|
|
|
if (bo != batch->bo &&
|
|
|
|
|
(!batch->measure || bo != batch->measure->bo)) {
|
2019-01-02 02:45:00 -08:00
|
|
|
/* This is the first time our batch has seen this BO. Before we use it,
|
|
|
|
|
* we may need to flush and synchronize with other batches.
|
2018-11-19 21:49:56 -08:00
|
|
|
*/
|
2019-01-02 02:45:00 -08:00
|
|
|
for (int b = 0; b < ARRAY_SIZE(batch->other_batches); b++) {
|
|
|
|
|
struct drm_i915_gem_exec_object2 *other_entry =
|
|
|
|
|
find_validation_entry(batch->other_batches[b], bo);
|
|
|
|
|
|
|
|
|
|
/* If the buffer is referenced by another batch, and either batch
|
|
|
|
|
* intends to write it, then flush the other batch and synchronize.
|
|
|
|
|
*
|
|
|
|
|
* Consider these cases:
|
|
|
|
|
*
|
|
|
|
|
* 1. They read, we read => No synchronization required.
|
|
|
|
|
* 2. They read, we write => Synchronize (they need the old value)
|
|
|
|
|
* 3. They write, we read => Synchronize (we need their new value)
|
|
|
|
|
* 4. They write, we write => Synchronize (order writes)
|
|
|
|
|
*
|
|
|
|
|
* The read/read case is very common, as multiple batches usually
|
|
|
|
|
* share a streaming state buffer or shader assembly buffer, and
|
|
|
|
|
* we want to avoid synchronizing in this case.
|
|
|
|
|
*/
|
|
|
|
|
if (other_entry &&
|
|
|
|
|
((other_entry->flags & EXEC_OBJECT_WRITE) || writable)) {
|
|
|
|
|
iris_batch_flush(batch->other_batches[b]);
|
2020-02-18 22:22:51 +00:00
|
|
|
iris_batch_add_syncobj(batch,
|
2020-05-27 22:19:52 +01:00
|
|
|
batch->other_batches[b]->last_fence->syncobj,
|
2020-04-28 23:24:38 -07:00
|
|
|
I915_EXEC_FENCE_WAIT);
|
2019-01-02 02:45:00 -08:00
|
|
|
}
|
2018-11-19 21:49:56 -08:00
|
|
|
}
|
2018-11-06 21:34:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now, take a reference and add it to the validation list. */
|
2017-11-23 23:15:14 -08:00
|
|
|
iris_bo_reference(bo);
|
|
|
|
|
|
2018-04-28 01:56:59 -07:00
|
|
|
ensure_exec_obj_space(batch, 1);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
|
|
|
|
batch->validation_list[batch->exec_count] =
|
|
|
|
|
(struct drm_i915_gem_exec_object2) {
|
|
|
|
|
.handle = bo->gem_handle,
|
|
|
|
|
.offset = bo->gtt_offset,
|
2018-11-19 21:40:54 -08:00
|
|
|
.flags = bo->kflags | (writable ? EXEC_OBJECT_WRITE : 0),
|
2017-11-23 23:15:14 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bo->index = batch->exec_count;
|
|
|
|
|
batch->exec_bos[batch->exec_count] = bo;
|
|
|
|
|
batch->aperture_space += bo->size;
|
|
|
|
|
|
2018-11-19 21:40:54 -08:00
|
|
|
batch->exec_count++;
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2018-05-02 19:54:23 -07:00
|
|
|
create_batch(struct iris_batch *batch)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = batch->screen;
|
|
|
|
|
struct iris_bufmgr *bufmgr = screen->bufmgr;
|
|
|
|
|
|
2018-05-02 19:54:23 -07:00
|
|
|
batch->bo = iris_bo_alloc(bufmgr, "command buffer",
|
|
|
|
|
BATCH_SZ + BATCH_RESERVED, IRIS_MEMZONE_OTHER);
|
|
|
|
|
batch->bo->kflags |= EXEC_OBJECT_CAPTURE;
|
|
|
|
|
batch->map = iris_bo_map(NULL, batch->bo, MAP_READ | MAP_WRITE);
|
|
|
|
|
batch->map_next = batch->map;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2020-05-29 16:38:43 -07:00
|
|
|
iris_use_pinned_bo(batch, batch->bo, false, IRIS_DOMAIN_NONE);
|
2018-05-02 19:54:23 -07:00
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2019-12-05 14:49:12 +02:00
|
|
|
static void
|
|
|
|
|
iris_batch_maybe_noop(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
/* We only insert the NOOP at the beginning of the batch. */
|
|
|
|
|
assert(iris_batch_bytes_used(batch) == 0);
|
|
|
|
|
|
|
|
|
|
if (batch->noop_enabled) {
|
|
|
|
|
/* Emit MI_BATCH_BUFFER_END to prevent any further command to be
|
|
|
|
|
* executed.
|
|
|
|
|
*/
|
|
|
|
|
uint32_t *map = batch->map_next;
|
|
|
|
|
|
|
|
|
|
map[0] = (0xA << 23);
|
|
|
|
|
|
|
|
|
|
batch->map_next += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-02 19:54:23 -07:00
|
|
|
static void
|
|
|
|
|
iris_batch_reset(struct iris_batch *batch)
|
|
|
|
|
{
|
2018-11-09 15:02:12 +00:00
|
|
|
struct iris_screen *screen = batch->screen;
|
|
|
|
|
|
2018-11-19 14:16:03 -08:00
|
|
|
iris_bo_unreference(batch->bo);
|
2018-05-02 19:54:23 -07:00
|
|
|
batch->primary_batch_size = 0;
|
2020-01-13 16:14:24 -08:00
|
|
|
batch->total_chained_batch_size = 0;
|
2018-10-02 20:09:01 -07:00
|
|
|
batch->contains_draw = false;
|
2021-02-14 20:28:02 +02:00
|
|
|
batch->contains_fence_signal = false;
|
2019-07-12 13:52:35 -07:00
|
|
|
batch->decoder.surface_base = batch->last_surface_base_address;
|
2018-05-02 19:54:23 -07:00
|
|
|
|
|
|
|
|
create_batch(batch);
|
|
|
|
|
assert(batch->bo->index == 0);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2020-04-28 23:24:38 -07:00
|
|
|
struct iris_syncobj *syncobj = iris_create_syncobj(screen);
|
|
|
|
|
iris_batch_add_syncobj(batch, syncobj, I915_EXEC_FENCE_SIGNAL);
|
|
|
|
|
iris_syncobj_reference(screen, &syncobj, NULL);
|
2018-11-09 15:02:12 +00:00
|
|
|
|
2020-05-27 13:34:04 -07:00
|
|
|
assert(!batch->sync_region_depth);
|
|
|
|
|
iris_batch_sync_boundary(batch);
|
2020-02-18 20:48:23 -08:00
|
|
|
iris_batch_mark_reset_sync(batch);
|
2020-05-27 13:34:04 -07:00
|
|
|
|
2019-12-24 02:41:10 +02:00
|
|
|
/* Always add the workaround BO, it contains a driver identifier at the
|
|
|
|
|
* beginning quite helpful to debug error states.
|
|
|
|
|
*/
|
2020-05-29 16:38:43 -07:00
|
|
|
iris_use_pinned_bo(batch, screen->workaround_bo, false, IRIS_DOMAIN_NONE);
|
2019-12-24 02:41:10 +02:00
|
|
|
|
2019-12-05 14:49:12 +02:00
|
|
|
iris_batch_maybe_noop(batch);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
iris_batch_free(struct iris_batch *batch)
|
|
|
|
|
{
|
2018-11-07 09:35:19 -08:00
|
|
|
struct iris_screen *screen = batch->screen;
|
|
|
|
|
struct iris_bufmgr *bufmgr = screen->bufmgr;
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
for (int i = 0; i < batch->exec_count; i++) {
|
|
|
|
|
iris_bo_unreference(batch->exec_bos[i]);
|
|
|
|
|
}
|
|
|
|
|
free(batch->exec_bos);
|
|
|
|
|
free(batch->validation_list);
|
2018-11-08 14:42:00 -08:00
|
|
|
|
|
|
|
|
ralloc_free(batch->exec_fences.mem_ctx);
|
|
|
|
|
|
2020-05-27 22:19:52 +01:00
|
|
|
pipe_resource_reference(&batch->fine_fences.ref.res, NULL);
|
2020-02-18 22:22:51 +00:00
|
|
|
|
2020-04-28 23:24:38 -07:00
|
|
|
util_dynarray_foreach(&batch->syncobjs, struct iris_syncobj *, s)
|
|
|
|
|
iris_syncobj_reference(screen, s, NULL);
|
|
|
|
|
ralloc_free(batch->syncobjs.mem_ctx);
|
2018-11-09 15:02:12 +00:00
|
|
|
|
2020-05-27 22:19:52 +01:00
|
|
|
iris_fine_fence_reference(batch->screen, &batch->last_fence, NULL);
|
|
|
|
|
u_upload_destroy(batch->fine_fences.uploader);
|
2018-11-19 20:41:26 -08:00
|
|
|
|
2018-05-02 19:54:23 -07:00
|
|
|
iris_bo_unreference(batch->bo);
|
|
|
|
|
batch->bo = NULL;
|
|
|
|
|
batch->map = NULL;
|
|
|
|
|
batch->map_next = NULL;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-11-07 09:35:19 -08:00
|
|
|
iris_destroy_hw_context(bufmgr, batch->hw_ctx_id);
|
|
|
|
|
|
2020-10-27 15:56:06 -07:00
|
|
|
iris_destroy_batch_measure(batch->measure);
|
|
|
|
|
batch->measure = NULL;
|
|
|
|
|
|
2018-04-20 23:28:03 -07:00
|
|
|
_mesa_hash_table_destroy(batch->cache.render, NULL);
|
|
|
|
|
|
2020-09-14 18:49:43 +02:00
|
|
|
if (INTEL_DEBUG)
|
2018-04-06 16:21:21 -07:00
|
|
|
gen_batch_decode_ctx_finish(&batch->decoder);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2018-05-02 19:54:23 -07:00
|
|
|
/**
|
|
|
|
|
* If we've chained to a secondary batch, or are getting near to the end,
|
|
|
|
|
* then flush. This should only be called between draws.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
iris_batch_maybe_flush(struct iris_batch *batch, unsigned estimate)
|
2017-12-27 02:25:20 -08:00
|
|
|
{
|
2018-05-02 19:54:23 -07:00
|
|
|
if (batch->bo != batch->exec_bos[0] ||
|
2018-08-19 10:31:29 -07:00
|
|
|
iris_batch_bytes_used(batch) + estimate >= BATCH_SZ) {
|
2017-12-27 02:25:20 -08:00
|
|
|
iris_batch_flush(batch);
|
|
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2020-01-13 16:14:24 -08:00
|
|
|
static void
|
|
|
|
|
record_batch_sizes(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
unsigned batch_size = iris_batch_bytes_used(batch);
|
|
|
|
|
|
|
|
|
|
VG(VALGRIND_CHECK_MEM_IS_DEFINED(batch->map, batch_size));
|
|
|
|
|
|
|
|
|
|
if (batch->bo == batch->exec_bos[0])
|
|
|
|
|
batch->primary_batch_size = batch_size;
|
|
|
|
|
|
|
|
|
|
batch->total_chained_batch_size += batch_size;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
void
|
2018-08-19 10:31:29 -07:00
|
|
|
iris_chain_to_new_batch(struct iris_batch *batch)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
2018-08-19 10:31:29 -07:00
|
|
|
uint32_t *cmd = batch->map_next;
|
|
|
|
|
uint64_t *addr = batch->map_next + 4;
|
2019-03-22 09:29:40 -07:00
|
|
|
batch->map_next += 12;
|
2017-12-27 02:25:20 -08:00
|
|
|
|
2020-01-13 16:14:24 -08:00
|
|
|
record_batch_sizes(batch);
|
|
|
|
|
|
2018-08-19 10:31:29 -07:00
|
|
|
/* No longer held by batch->bo, still held by validation list */
|
|
|
|
|
iris_bo_unreference(batch->bo);
|
|
|
|
|
create_batch(batch);
|
2018-04-20 17:42:07 -07:00
|
|
|
|
2018-08-19 10:31:29 -07:00
|
|
|
/* Emit MI_BATCH_BUFFER_START to chain to another batch. */
|
|
|
|
|
*cmd = (0x31 << 23) | (1 << 8) | (3 - 2);
|
|
|
|
|
*addr = batch->bo->gtt_offset;
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2018-04-28 01:56:59 -07:00
|
|
|
static void
|
|
|
|
|
add_aux_map_bos_to_batch(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
void *aux_map_ctx = iris_bufmgr_get_aux_map_context(batch->screen->bufmgr);
|
|
|
|
|
if (!aux_map_ctx)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
uint32_t count = gen_aux_map_get_num_buffers(aux_map_ctx);
|
|
|
|
|
ensure_exec_obj_space(batch, count);
|
|
|
|
|
gen_aux_map_fill_bos(aux_map_ctx,
|
|
|
|
|
(void**)&batch->exec_bos[batch->exec_count], count);
|
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
|
struct iris_bo *bo = batch->exec_bos[batch->exec_count];
|
|
|
|
|
iris_bo_reference(bo);
|
|
|
|
|
batch->validation_list[batch->exec_count] =
|
|
|
|
|
(struct drm_i915_gem_exec_object2) {
|
|
|
|
|
.handle = bo->gem_handle,
|
|
|
|
|
.offset = bo->gtt_offset,
|
|
|
|
|
.flags = bo->kflags,
|
|
|
|
|
};
|
|
|
|
|
batch->aperture_space += bo->size;
|
|
|
|
|
batch->exec_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 22:22:51 +00:00
|
|
|
static void
|
|
|
|
|
finish_seqno(struct iris_batch *batch)
|
|
|
|
|
{
|
2020-05-27 22:19:52 +01:00
|
|
|
struct iris_fine_fence *sq = iris_fine_fence_new(batch, IRIS_FENCE_END);
|
2020-02-18 22:22:51 +00:00
|
|
|
if (!sq)
|
|
|
|
|
return;
|
|
|
|
|
|
2020-05-27 22:19:52 +01:00
|
|
|
iris_fine_fence_reference(batch->screen, &batch->last_fence, sq);
|
|
|
|
|
iris_fine_fence_reference(batch->screen, &sq, NULL);
|
2020-02-18 22:22:51 +00:00
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
/**
|
2018-06-23 12:18:11 -07:00
|
|
|
* Terminate a batch with MI_BATCH_BUFFER_END.
|
2017-11-23 23:15:14 -08:00
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
iris_finish_batch(struct iris_batch *batch)
|
|
|
|
|
{
|
2018-04-28 01:56:59 -07:00
|
|
|
add_aux_map_bos_to_batch(batch);
|
|
|
|
|
|
2020-02-18 22:22:51 +00:00
|
|
|
finish_seqno(batch);
|
|
|
|
|
|
2018-07-31 17:32:47 -07:00
|
|
|
/* Emit MI_BATCH_BUFFER_END to finish our batch. */
|
2018-05-02 21:52:34 -07:00
|
|
|
uint32_t *map = batch->map_next;
|
|
|
|
|
|
|
|
|
|
map[0] = (0xA << 23);
|
|
|
|
|
|
2018-07-31 17:32:47 -07:00
|
|
|
batch->map_next += 4;
|
2018-06-23 12:48:37 -07:00
|
|
|
|
2020-01-13 16:14:24 -08:00
|
|
|
record_batch_sizes(batch);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2019-05-07 23:19:30 -07:00
|
|
|
/**
|
|
|
|
|
* Replace our current GEM context with a new one (in case it got banned).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
replace_hw_ctx(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = batch->screen;
|
|
|
|
|
struct iris_bufmgr *bufmgr = screen->bufmgr;
|
|
|
|
|
|
|
|
|
|
uint32_t new_ctx = iris_clone_hw_context(bufmgr, batch->hw_ctx_id);
|
|
|
|
|
if (!new_ctx)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
iris_destroy_hw_context(bufmgr, batch->hw_ctx_id);
|
|
|
|
|
batch->hw_ctx_id = new_ctx;
|
|
|
|
|
|
|
|
|
|
/* Notify the context that state must be re-initialized. */
|
|
|
|
|
iris_lost_context_state(batch);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-08 11:33:50 -07:00
|
|
|
enum pipe_reset_status
|
|
|
|
|
iris_batch_check_for_reset(struct iris_batch *batch)
|
|
|
|
|
{
|
|
|
|
|
struct iris_screen *screen = batch->screen;
|
|
|
|
|
enum pipe_reset_status status = PIPE_NO_RESET;
|
|
|
|
|
struct drm_i915_reset_stats stats = { .ctx_id = batch->hw_ctx_id };
|
|
|
|
|
|
|
|
|
|
if (drmIoctl(screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats))
|
|
|
|
|
DBG("DRM_IOCTL_I915_GET_RESET_STATS failed: %s\n", strerror(errno));
|
|
|
|
|
|
|
|
|
|
if (stats.batch_active != 0) {
|
|
|
|
|
/* A reset was observed while a batch from this hardware context was
|
|
|
|
|
* executing. Assume that this context was at fault.
|
|
|
|
|
*/
|
|
|
|
|
status = PIPE_GUILTY_CONTEXT_RESET;
|
|
|
|
|
} else if (stats.batch_pending != 0) {
|
|
|
|
|
/* A reset was observed while a batch from this context was in progress,
|
|
|
|
|
* but the batch was not executing. In this case, assume that the
|
|
|
|
|
* context was not at fault.
|
|
|
|
|
*/
|
|
|
|
|
status = PIPE_INNOCENT_CONTEXT_RESET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status != PIPE_NO_RESET) {
|
|
|
|
|
/* Our context is likely banned, or at least in an unknown state.
|
|
|
|
|
* Throw it away and start with a fresh context. Ideally this may
|
|
|
|
|
* catch the problem before our next execbuf fails with -EIO.
|
|
|
|
|
*/
|
|
|
|
|
replace_hw_ctx(batch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-30 23:49:34 -07:00
|
|
|
/**
|
|
|
|
|
* Submit the batch to the GPU via execbuffer2.
|
|
|
|
|
*/
|
2017-11-23 23:15:14 -08:00
|
|
|
static int
|
2018-11-08 14:42:00 -08:00
|
|
|
submit_batch(struct iris_batch *batch)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
2018-05-02 19:54:23 -07:00
|
|
|
iris_bo_unmap(batch->bo);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
|
|
|
|
/* The requirement for using I915_EXEC_NO_RELOC are:
|
|
|
|
|
*
|
|
|
|
|
* The addresses written in the objects must match the corresponding
|
|
|
|
|
* reloc.gtt_offset which in turn must match the corresponding
|
|
|
|
|
* execobject.offset.
|
|
|
|
|
*
|
|
|
|
|
* Any render targets written to in the batch must be flagged with
|
|
|
|
|
* EXEC_OBJECT_WRITE.
|
|
|
|
|
*
|
|
|
|
|
* To avoid stalling, execobject.offset should match the current
|
|
|
|
|
* address of that object within the active context.
|
|
|
|
|
*/
|
|
|
|
|
struct drm_i915_gem_execbuffer2 execbuf = {
|
|
|
|
|
.buffers_ptr = (uintptr_t) batch->validation_list,
|
|
|
|
|
.buffer_count = batch->exec_count,
|
|
|
|
|
.batch_start_offset = 0,
|
2018-07-31 17:32:47 -07:00
|
|
|
/* This must be QWord aligned. */
|
|
|
|
|
.batch_len = ALIGN(batch->primary_batch_size, 8),
|
2019-09-03 07:19:32 -07:00
|
|
|
.flags = I915_EXEC_RENDER |
|
2018-01-20 23:11:37 -08:00
|
|
|
I915_EXEC_NO_RELOC |
|
2017-12-27 02:25:20 -08:00
|
|
|
I915_EXEC_BATCH_FIRST |
|
2018-01-20 23:11:37 -08:00
|
|
|
I915_EXEC_HANDLE_LUT,
|
2017-11-23 23:15:14 -08:00
|
|
|
.rsvd1 = batch->hw_ctx_id, /* rsvd1 is actually the context ID */
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-08 14:42:00 -08:00
|
|
|
if (num_fences(batch)) {
|
|
|
|
|
execbuf.flags |= I915_EXEC_FENCE_ARRAY;
|
|
|
|
|
execbuf.num_cliprects = num_fences(batch);
|
|
|
|
|
execbuf.cliprects_ptr =
|
|
|
|
|
(uintptr_t)util_dynarray_begin(&batch->exec_fences);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-25 22:32:12 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
if (!batch->screen->no_hw &&
|
2019-07-25 10:50:36 -07:00
|
|
|
gen_ioctl(batch->screen->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf))
|
2017-11-23 23:15:14 -08:00
|
|
|
ret = -errno;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < batch->exec_count; i++) {
|
|
|
|
|
struct iris_bo *bo = batch->exec_bos[i];
|
|
|
|
|
|
|
|
|
|
bo->idle = false;
|
|
|
|
|
bo->index = -1;
|
2018-11-19 14:12:52 -08:00
|
|
|
|
|
|
|
|
iris_bo_unreference(bo);
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-20 09:00:22 -08:00
|
|
|
static const char *
|
|
|
|
|
batch_name_to_string(enum iris_batch_name name)
|
|
|
|
|
{
|
|
|
|
|
const char *names[IRIS_BATCH_COUNT] = {
|
|
|
|
|
[IRIS_BATCH_RENDER] = "render",
|
|
|
|
|
[IRIS_BATCH_COMPUTE] = "compute",
|
|
|
|
|
};
|
|
|
|
|
return names[name];
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
/**
|
2018-07-30 23:49:34 -07:00
|
|
|
* Flush the batch buffer, submitting it to the GPU and resetting it so
|
|
|
|
|
* we're ready to emit the next batch.
|
2017-11-23 23:15:14 -08:00
|
|
|
*/
|
2018-11-08 14:42:00 -08:00
|
|
|
void
|
|
|
|
|
_iris_batch_flush(struct iris_batch *batch, const char *file, int line)
|
2017-11-23 23:15:14 -08:00
|
|
|
{
|
2018-11-09 15:02:12 +00:00
|
|
|
struct iris_screen *screen = batch->screen;
|
|
|
|
|
|
2021-02-14 20:28:02 +02:00
|
|
|
/* If a fence signals we need to flush it. */
|
|
|
|
|
if (iris_batch_bytes_used(batch) == 0 && !batch->contains_fence_signal)
|
2018-11-08 14:42:00 -08:00
|
|
|
return;
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2020-10-27 15:56:06 -07:00
|
|
|
iris_measure_batch_end(batch->ice, batch);
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
iris_finish_batch(batch);
|
|
|
|
|
|
2020-09-14 18:49:43 +02:00
|
|
|
if (INTEL_DEBUG & (DEBUG_BATCH | DEBUG_SUBMIT | DEBUG_PIPE_CONTROL)) {
|
2020-02-11 11:36:09 -08:00
|
|
|
const char *basefile = strstr(file, "iris/");
|
|
|
|
|
if (basefile)
|
|
|
|
|
file = basefile + 5;
|
|
|
|
|
|
2020-01-13 16:14:24 -08:00
|
|
|
fprintf(stderr, "%19s:%-3d: %s batch [%u] flush with %5db (%0.1f%%) "
|
2018-09-08 19:43:34 -07:00
|
|
|
"(cmds), %4d BOs (%0.1fMb aperture)\n",
|
2018-11-20 09:00:22 -08:00
|
|
|
file, line, batch_name_to_string(batch->name), batch->hw_ctx_id,
|
2020-01-13 16:14:24 -08:00
|
|
|
batch->total_chained_batch_size,
|
|
|
|
|
100.0f * batch->total_chained_batch_size / BATCH_SZ,
|
2017-11-23 23:15:14 -08:00
|
|
|
batch->exec_count,
|
2018-04-06 00:05:24 -07:00
|
|
|
(float) batch->aperture_space / (1024 * 1024));
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2019-06-19 16:04:50 -05:00
|
|
|
if (INTEL_DEBUG & (DEBUG_BATCH | DEBUG_SUBMIT)) {
|
|
|
|
|
dump_fence_list(batch);
|
|
|
|
|
dump_validation_list(batch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (INTEL_DEBUG & DEBUG_BATCH) {
|
|
|
|
|
decode_batch(batch);
|
|
|
|
|
}
|
2018-05-02 19:54:23 -07:00
|
|
|
}
|
2018-04-06 16:21:21 -07:00
|
|
|
|
2018-11-08 14:42:00 -08:00
|
|
|
int ret = submit_batch(batch);
|
2017-11-23 23:15:14 -08:00
|
|
|
|
2018-01-20 23:14:24 -08:00
|
|
|
batch->exec_count = 0;
|
|
|
|
|
batch->aperture_space = 0;
|
|
|
|
|
|
2020-04-28 23:24:38 -07:00
|
|
|
util_dynarray_foreach(&batch->syncobjs, struct iris_syncobj *, s)
|
|
|
|
|
iris_syncobj_reference(screen, s, NULL);
|
|
|
|
|
util_dynarray_clear(&batch->syncobjs);
|
2018-11-09 15:02:12 +00:00
|
|
|
|
2018-11-08 14:42:00 -08:00
|
|
|
util_dynarray_clear(&batch->exec_fences);
|
|
|
|
|
|
2020-09-14 18:49:43 +02:00
|
|
|
if (INTEL_DEBUG & DEBUG_SYNC) {
|
2019-03-25 22:32:12 +00:00
|
|
|
dbg_printf("waiting for idle\n");
|
|
|
|
|
iris_bo_wait_rendering(batch->bo); /* if execbuf failed; this is a nop */
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 23:15:14 -08:00
|
|
|
/* Start a new batch buffer. */
|
2018-05-02 14:28:27 -07:00
|
|
|
iris_batch_reset(batch);
|
2019-03-25 22:32:12 +00:00
|
|
|
|
2019-05-07 23:19:30 -07:00
|
|
|
/* EIO means our context is banned. In this case, try and replace it
|
|
|
|
|
* with a new logical context, and inform iris_context that all state
|
|
|
|
|
* has been lost and needs to be re-initialized. If this succeeds,
|
|
|
|
|
* dubiously claim success...
|
|
|
|
|
*/
|
|
|
|
|
if (ret == -EIO && replace_hw_ctx(batch)) {
|
2019-05-07 22:26:22 -07:00
|
|
|
if (batch->reset->reset) {
|
2019-12-03 20:38:14 -05:00
|
|
|
/* Tell gallium frontends the device is lost and it was our fault. */
|
2019-05-07 22:26:22 -07:00
|
|
|
batch->reset->reset(batch->reset->data, PIPE_GUILTY_CONTEXT_RESET);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-07 23:19:30 -07:00
|
|
|
ret = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-03 15:12:17 -07:00
|
|
|
if (ret < 0) {
|
2019-03-25 22:32:12 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
const bool color = INTEL_DEBUG & DEBUG_COLOR;
|
|
|
|
|
fprintf(stderr, "%siris: Failed to submit batchbuffer: %-80s%s\n",
|
|
|
|
|
color ? "\e[1;41m" : "", strerror(-ret), color ? "\e[0m" : "");
|
|
|
|
|
#endif
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2017-11-23 23:15:14 -08:00
|
|
|
}
|
|
|
|
|
|
2018-07-30 23:49:34 -07:00
|
|
|
/**
|
|
|
|
|
* Does the current batch refer to the given BO?
|
|
|
|
|
*
|
|
|
|
|
* (In other words, is the BO in the current batch's validation list?)
|
|
|
|
|
*/
|
2017-11-23 23:15:14 -08:00
|
|
|
bool
|
|
|
|
|
iris_batch_references(struct iris_batch *batch, struct iris_bo *bo)
|
|
|
|
|
{
|
2018-11-19 21:40:54 -08:00
|
|
|
return find_validation_entry(batch, bo) != NULL;
|
2018-01-30 02:16:34 -08:00
|
|
|
}
|
2019-12-05 14:49:12 +02:00
|
|
|
|
|
|
|
|
/**
|
2020-05-29 16:54:35 -07:00
|
|
|
* Updates the state of the noop feature. Returns true if there was a noop
|
|
|
|
|
* transition that led to state invalidation.
|
2019-12-05 14:49:12 +02:00
|
|
|
*/
|
2020-05-29 16:54:35 -07:00
|
|
|
bool
|
|
|
|
|
iris_batch_prepare_noop(struct iris_batch *batch, bool noop_enable)
|
2019-12-05 14:49:12 +02:00
|
|
|
{
|
|
|
|
|
if (batch->noop_enabled == noop_enable)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
batch->noop_enabled = noop_enable;
|
|
|
|
|
|
|
|
|
|
iris_batch_flush(batch);
|
|
|
|
|
|
|
|
|
|
/* If the batch was empty, flush had no effect, so insert our noop. */
|
|
|
|
|
if (iris_batch_bytes_used(batch) == 0)
|
|
|
|
|
iris_batch_maybe_noop(batch);
|
|
|
|
|
|
|
|
|
|
/* We only need to update the entire state if we transition from noop ->
|
|
|
|
|
* not-noop.
|
|
|
|
|
*/
|
2020-05-29 16:54:35 -07:00
|
|
|
return !batch->noop_enabled;
|
2019-12-05 14:49:12 +02:00
|
|
|
}
|