#include "anv_private.h"
#include "genxml/gen8_pack.h"
+#include "genxml/genX_bits.h"
#include "util/debug.h"
return address_u64;
}
+struct anv_address
+anv_batch_address(struct anv_batch *batch, void *batch_location)
+{
+ assert(batch->start < batch_location);
+
+ /* Allow a jump at the current location of the batch. */
+ assert(batch->next >= batch_location);
+
+ return anv_address_add(batch->start_addr, batch_location - batch->start);
+}
+
void
anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other)
{
anv_batch_bo_start(struct anv_batch_bo *bbo, struct anv_batch *batch,
size_t batch_padding)
{
+ batch->start_addr = (struct anv_address) { .bo = bbo->bo, };
batch->next = batch->start = bbo->bo->map;
batch->end = bbo->bo->map + bbo->bo->size - batch_padding;
batch->relocs = &bbo->relocs;
anv_batch_bo_continue(struct anv_batch_bo *bbo, struct anv_batch *batch,
size_t batch_padding)
{
+ batch->start_addr = (struct anv_address) { .bo = bbo->bo, };
batch->start = bbo->bo->map;
batch->next = bbo->bo->map + bbo->length;
batch->end = bbo->bo->map + bbo->bo->size - batch_padding;
const uint32_t length = cmd_buffer->batch.next - cmd_buffer->batch.start;
if (!cmd_buffer->device->can_chain_batches) {
cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_GROW_AND_EMIT;
+ } else if (cmd_buffer->device->physical->use_softpin) {
+ cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_CALL_AND_RETURN;
+ /* If the secondary command buffer begins & ends in the same BO and
+ * its length is less than the length of CS prefetch, add some NOOPs
+ * instructions so the last MI_BATCH_BUFFER_START is outside the CS
+ * prefetch.
+ */
+ if (cmd_buffer->batch_bos.next == cmd_buffer->batch_bos.prev) {
+ int32_t batch_len =
+ cmd_buffer->batch.next - cmd_buffer->batch.start;
+
+ for (int32_t i = 0; i < (512 - batch_len); i += 4)
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_NOOP, noop);
+ }
+
+ void *jump_addr =
+ anv_batch_emitn(&cmd_buffer->batch,
+ GEN8_MI_BATCH_BUFFER_START_length,
+ GEN8_MI_BATCH_BUFFER_START,
+ .AddressSpaceIndicator = ASI_PPGTT,
+ .SecondLevelBatchBuffer = Firstlevelbatch) +
+ (GEN8_MI_BATCH_BUFFER_START_BatchBufferStartAddress_start / 8);
+ cmd_buffer->return_addr = anv_batch_address(&cmd_buffer->batch, jump_addr);
} else if ((cmd_buffer->batch_bos.next == cmd_buffer->batch_bos.prev) &&
(length < ANV_CMD_BUFFER_BATCH_SIZE / 2)) {
/* If the secondary has exactly one batch buffer in its list *and*
GEN8_MI_BATCH_BUFFER_START_length * 4);
break;
}
+ case ANV_CMD_BUFFER_EXEC_MODE_CALL_AND_RETURN: {
+ struct anv_batch_bo *first_bbo =
+ list_first_entry(&secondary->batch_bos, struct anv_batch_bo, link);
+
+ uint64_t *write_return_addr =
+ anv_batch_emitn(&primary->batch,
+ GEN8_MI_STORE_DATA_IMM_length + 1 /* QWord write */,
+ GEN8_MI_STORE_DATA_IMM,
+ .Address = secondary->return_addr)
+ + (GEN8_MI_STORE_DATA_IMM_ImmediateData_start / 8);
+
+ emit_batch_buffer_start(primary, first_bbo->bo, 0);
+
+ *write_return_addr =
+ anv_address_physical(anv_batch_address(&primary->batch,
+ primary->batch.next));
+
+ anv_cmd_buffer_add_seen_bbos(primary, &secondary->batch_bos);
+ break;
+ }
default:
assert(!"Invalid execution mode");
}
struct anv_reloc_list relocs;
};
+struct anv_address {
+ struct anv_bo *bo;
+ uint32_t offset;
+};
+
struct anv_batch {
const VkAllocationCallbacks * alloc;
+ struct anv_address start_addr;
+
void * start;
void * end;
void * next;
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
void *location, struct anv_bo *bo, uint32_t offset);
+struct anv_address anv_batch_address(struct anv_batch *batch, void *batch_location);
static inline VkResult
anv_batch_set_error(struct anv_batch *batch, VkResult error)
return batch->status != VK_SUCCESS;
}
-struct anv_address {
- struct anv_bo *bo;
- uint32_t offset;
-};
-
#define ANV_NULL_ADDRESS ((struct anv_address) { NULL, 0 })
static inline bool
ANV_CMD_BUFFER_EXEC_MODE_GROW_AND_EMIT,
ANV_CMD_BUFFER_EXEC_MODE_CHAIN,
ANV_CMD_BUFFER_EXEC_MODE_COPY_AND_CHAIN,
+ ANV_CMD_BUFFER_EXEC_MODE_CALL_AND_RETURN,
};
struct anv_cmd_buffer {
struct anv_cmd_state state;
+ struct anv_address return_addr;
+
/* Set by SetPerformanceMarkerINTEL, written into queries by CmdBeginQuery */
uint64_t intel_perf_marker;
};