anv: Move mi_memcpy and mi_memset to gen_mi_builder
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
This commit is contained in:
@@ -51,80 +51,6 @@ gcd_pow2_u64(uint64_t a, uint64_t b)
|
||||
return 1 << MIN2(a_log2, b_log2);
|
||||
}
|
||||
|
||||
void
|
||||
genX(cmd_buffer_mi_memcpy)(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_address dst, struct anv_address src,
|
||||
uint32_t size)
|
||||
{
|
||||
/* This memcpy operates in units of dwords. */
|
||||
assert(size % 4 == 0);
|
||||
assert(dst.offset % 4 == 0);
|
||||
assert(src.offset % 4 == 0);
|
||||
|
||||
#if GEN_GEN == 7
|
||||
/* On gen7, the combination of commands used here(MI_LOAD_REGISTER_MEM
|
||||
* and MI_STORE_REGISTER_MEM) can cause GPU hangs if any rendering is
|
||||
* in-flight when they are issued even if the memory touched is not
|
||||
* currently active for rendering. The weird bit is that it is not the
|
||||
* MI_LOAD/STORE_REGISTER_MEM commands which hang but rather the in-flight
|
||||
* rendering hangs such that the next stalling command after the
|
||||
* MI_LOAD/STORE_REGISTER_MEM commands will catch the hang.
|
||||
*
|
||||
* It is unclear exactly why this hang occurs. Both MI commands come with
|
||||
* warnings about the 3D pipeline but that doesn't seem to fully explain
|
||||
* it. My (Jason's) best theory is that it has something to do with the
|
||||
* fact that we're using a GPU state register as our temporary and that
|
||||
* something with reading/writing it is causing problems.
|
||||
*
|
||||
* In order to work around this issue, we emit a PIPE_CONTROL with the
|
||||
* command streamer stall bit set.
|
||||
*/
|
||||
cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_CS_STALL_BIT;
|
||||
genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer);
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < size; i += 4) {
|
||||
#if GEN_GEN >= 8
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(MI_COPY_MEM_MEM), cp) {
|
||||
cp.DestinationMemoryAddress = anv_address_add(dst, i);
|
||||
cp.SourceMemoryAddress = anv_address_add(src, i);
|
||||
}
|
||||
#else
|
||||
/* IVB does not have a general purpose register for command streamer
|
||||
* commands. Therefore, we use an alternate temporary register.
|
||||
*/
|
||||
#define TEMP_REG 0x2440 /* GEN7_3DPRIM_BASE_VERTEX */
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(MI_LOAD_REGISTER_MEM), load) {
|
||||
load.RegisterAddress = TEMP_REG;
|
||||
load.MemoryAddress = anv_address_add(src, i);
|
||||
}
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_REGISTER_MEM), store) {
|
||||
store.RegisterAddress = TEMP_REG;
|
||||
store.MemoryAddress = anv_address_add(dst, i);
|
||||
}
|
||||
#undef TEMP_REG
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
genX(cmd_buffer_mi_memset)(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_address dst, uint32_t value,
|
||||
uint32_t size)
|
||||
{
|
||||
/* This memset operates in units of dwords. */
|
||||
assert(size % 4 == 0);
|
||||
assert(dst.offset % 4 == 0);
|
||||
|
||||
for (uint32_t i = 0; i < size; i += 4) {
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_DATA_IMM), sdi) {
|
||||
sdi.Address = anv_address_add(dst, i);
|
||||
sdi.ImmediateData = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
genX(cmd_buffer_so_memcpy)(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_address dst, struct anv_address src,
|
||||
|
Reference in New Issue
Block a user