static struct pipe_stream_output_target * r600_create_so_target(struct pipe_context *ctx, struct pipe_resource *buffer, unsigned buffer_offset, unsigned buffer_size) { struct r600_common_context *rctx = (struct r600_common_context *)ctx; struct r600_so_target *t; struct r600_resource *rbuffer = (struct r600_resource*)buffer; t = CALLOC_STRUCT(r600_so_target); if (!t) { return NULL; } u_suballocator_alloc(rctx->allocator_so_filled_size, 4, &t->buf_filled_size_offset, (struct pipe_resource**)&t->buf_filled_size); if (!t->buf_filled_size) { FREE(t); return NULL; } t->b.reference.count = 1; t->b.context = ctx; pipe_resource_reference(&t->b.buffer, buffer); t->b.buffer_offset = buffer_offset; t->b.buffer_size = buffer_size; util_range_add(&rbuffer->valid_buffer_range, buffer_offset, buffer_offset + buffer_size); return &t->b; }
void r600_emit_pfp_sync_me(struct r600_context *rctx) { struct radeon_winsys_cs *cs = rctx->b.gfx.cs; if (rctx->b.chip_class >= EVERGREEN && rctx->b.screen->info.drm_minor >= 46) { radeon_emit(cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0)); radeon_emit(cs, 0); } else { /* Emulate PFP_SYNC_ME by writing a value to memory in ME and * waiting for it in PFP. */ struct r600_resource *buf = NULL; unsigned offset, reloc; uint64_t va; /* 16-byte address alignment is required by WAIT_REG_MEM. */ u_suballocator_alloc(rctx->b.allocator_zeroed_memory, 4, 16, &offset, (struct pipe_resource**)&buf); if (!buf) { /* This is too heavyweight, but will work. */ rctx->b.gfx.flush(rctx, RADEON_FLUSH_ASYNC, NULL); return; } reloc = radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, buf, RADEON_USAGE_READWRITE, RADEON_PRIO_FENCE); va = buf->gpu_address + offset; assert(va % 16 == 0); /* Write 1 to memory in ME. */ radeon_emit(cs, PKT3(PKT3_MEM_WRITE, 3, 0)); radeon_emit(cs, va); radeon_emit(cs, ((va >> 32) & 0xff) | MEM_WRITE_32_BITS); radeon_emit(cs, 1); radeon_emit(cs, 0); radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); radeon_emit(cs, reloc); /* Wait in PFP (PFP can only do GEQUAL against memory). */ radeon_emit(cs, PKT3(PKT3_WAIT_REG_MEM, 5, 0)); radeon_emit(cs, WAIT_REG_MEM_GEQUAL | WAIT_REG_MEM_MEMORY | WAIT_REG_MEM_PFP); radeon_emit(cs, va); radeon_emit(cs, va >> 32); radeon_emit(cs, 1); /* reference value */ radeon_emit(cs, 0xffffffff); /* mask */ radeon_emit(cs, 4); /* poll interval */ radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); radeon_emit(cs, reloc); r600_resource_reference(&buf, NULL); } }
static bool si_ce_upload(struct si_context *sctx, unsigned ce_offset, unsigned size, unsigned *out_offset, struct r600_resource **out_buf) { uint64_t va; u_suballocator_alloc(sctx->ce_suballocator, size, out_offset, (struct pipe_resource**)out_buf); if (!out_buf) return false; va = (*out_buf)->gpu_address + *out_offset; radeon_emit(sctx->ce_ib, PKT3(PKT3_DUMP_CONST_RAM, 3, 0)); radeon_emit(sctx->ce_ib, ce_offset); radeon_emit(sctx->ce_ib, size / 4); radeon_emit(sctx->ce_ib, va); radeon_emit(sctx->ce_ib, va >> 32); radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, *out_buf, RADEON_USAGE_READWRITE, RADEON_PRIO_DESCRIPTORS); sctx->ce_need_synchronization = true; return true; }