1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2010 Jerome Glisse <glisse@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Jerome Glisse 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci#include "r600_pipe.h" 27bf215546Sopenharmony_ci#include "r600d.h" 28bf215546Sopenharmony_ci#include "util/u_memory.h" 29bf215546Sopenharmony_ci#include <errno.h> 30bf215546Sopenharmony_ci#include <unistd.h> 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_civoid r600_need_cs_space(struct r600_context *ctx, unsigned num_dw, 34bf215546Sopenharmony_ci boolean count_draw_in, unsigned num_atomics) 35bf215546Sopenharmony_ci{ 36bf215546Sopenharmony_ci /* Flush the DMA IB if it's not empty. */ 37bf215546Sopenharmony_ci if (radeon_emitted(&ctx->b.dma.cs, 0)) 38bf215546Sopenharmony_ci ctx->b.dma.flush(ctx, PIPE_FLUSH_ASYNC, NULL); 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci if (!radeon_cs_memory_below_limit(ctx->b.screen, &ctx->b.gfx.cs, 41bf215546Sopenharmony_ci ctx->b.vram, ctx->b.gtt)) { 42bf215546Sopenharmony_ci ctx->b.gtt = 0; 43bf215546Sopenharmony_ci ctx->b.vram = 0; 44bf215546Sopenharmony_ci ctx->b.gfx.flush(ctx, PIPE_FLUSH_ASYNC, NULL); 45bf215546Sopenharmony_ci return; 46bf215546Sopenharmony_ci } 47bf215546Sopenharmony_ci /* all will be accounted once relocation are emitted */ 48bf215546Sopenharmony_ci ctx->b.gtt = 0; 49bf215546Sopenharmony_ci ctx->b.vram = 0; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci /* Check available space in CS. */ 52bf215546Sopenharmony_ci if (count_draw_in) { 53bf215546Sopenharmony_ci uint64_t mask; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci /* The number of dwords all the dirty states would take. */ 56bf215546Sopenharmony_ci mask = ctx->dirty_atoms; 57bf215546Sopenharmony_ci while (mask != 0) 58bf215546Sopenharmony_ci num_dw += ctx->atoms[u_bit_scan64(&mask)]->num_dw; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci /* The upper-bound of how much space a draw command would take. */ 61bf215546Sopenharmony_ci num_dw += R600_MAX_FLUSH_CS_DWORDS + R600_MAX_DRAW_CS_DWORDS; 62bf215546Sopenharmony_ci } 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci /* add atomic counters, 8 pre + 8 post per counter + 16 post if any counters */ 65bf215546Sopenharmony_ci num_dw += (num_atomics * 16) + (num_atomics ? 16 : 0); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci /* Count in r600_suspend_queries. */ 68bf215546Sopenharmony_ci num_dw += ctx->b.num_cs_dw_queries_suspend; 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci /* Count in streamout_end at the end of CS. */ 71bf215546Sopenharmony_ci if (ctx->b.streamout.begin_emitted) { 72bf215546Sopenharmony_ci num_dw += ctx->b.streamout.num_dw_for_end; 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci /* SX_MISC */ 76bf215546Sopenharmony_ci if (ctx->b.gfx_level == R600) { 77bf215546Sopenharmony_ci num_dw += 3; 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci /* Count in framebuffer cache flushes at the end of CS. */ 81bf215546Sopenharmony_ci num_dw += R600_MAX_FLUSH_CS_DWORDS; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci /* The fence at the end of CS. */ 84bf215546Sopenharmony_ci num_dw += 10; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci /* Flush if there's not enough space. */ 87bf215546Sopenharmony_ci if (!ctx->b.ws->cs_check_space(&ctx->b.gfx.cs, num_dw)) { 88bf215546Sopenharmony_ci ctx->b.gfx.flush(ctx, PIPE_FLUSH_ASYNC, NULL); 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_civoid r600_flush_emit(struct r600_context *rctx) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->b.gfx.cs; 95bf215546Sopenharmony_ci unsigned cp_coher_cntl = 0; 96bf215546Sopenharmony_ci unsigned wait_until = 0; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci if (!rctx->b.flags) { 99bf215546Sopenharmony_ci return; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* Ensure coherency between streamout and shaders. */ 103bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_STREAMOUT_FLUSH) 104bf215546Sopenharmony_ci rctx->b.flags |= r600_get_flush_flags(R600_COHERENCY_SHADER); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_WAIT_3D_IDLE) { 107bf215546Sopenharmony_ci wait_until |= S_008040_WAIT_3D_IDLE(1); 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_WAIT_CP_DMA_IDLE) { 110bf215546Sopenharmony_ci wait_until |= S_008040_WAIT_CP_DMA_IDLE(1); 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (wait_until) { 114bf215546Sopenharmony_ci /* Use of WAIT_UNTIL is deprecated on Cayman+ */ 115bf215546Sopenharmony_ci if (rctx->b.family >= CHIP_CAYMAN) { 116bf215546Sopenharmony_ci /* emit a PS partial flush on Cayman/TN */ 117bf215546Sopenharmony_ci rctx->b.flags |= R600_CONTEXT_PS_PARTIAL_FLUSH; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci /* Wait packets must be executed first, because SURFACE_SYNC doesn't 122bf215546Sopenharmony_ci * wait for shaders if it's not flushing CB or DB. 123bf215546Sopenharmony_ci */ 124bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_PS_PARTIAL_FLUSH) { 125bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 126bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_PS_PARTIAL_FLUSH) | EVENT_INDEX(4)); 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_CS_PARTIAL_FLUSH) { 130bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 131bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_CS_PARTIAL_FLUSH) | EVENT_INDEX(4)); 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci if (wait_until) { 135bf215546Sopenharmony_ci /* Use of WAIT_UNTIL is deprecated on Cayman+ */ 136bf215546Sopenharmony_ci if (rctx->b.family < CHIP_CAYMAN) { 137bf215546Sopenharmony_ci /* wait for things to settle */ 138bf215546Sopenharmony_ci radeon_set_config_reg(cs, R_008040_WAIT_UNTIL, wait_until); 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (rctx->b.gfx_level >= R700 && 143bf215546Sopenharmony_ci (rctx->b.flags & R600_CONTEXT_FLUSH_AND_INV_CB_META)) { 144bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 145bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_FLUSH_AND_INV_CB_META) | EVENT_INDEX(0)); 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (rctx->b.gfx_level >= R700 && 149bf215546Sopenharmony_ci (rctx->b.flags & R600_CONTEXT_FLUSH_AND_INV_DB_META)) { 150bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 151bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_FLUSH_AND_INV_DB_META) | EVENT_INDEX(0)); 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci /* Set FULL_CACHE_ENA for DB META flushes on r7xx and later. 154bf215546Sopenharmony_ci * 155bf215546Sopenharmony_ci * This hack predates use of FLUSH_AND_INV_DB_META, so it's 156bf215546Sopenharmony_ci * unclear whether it's still needed or even whether it has 157bf215546Sopenharmony_ci * any effect. 158bf215546Sopenharmony_ci */ 159bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_FULL_CACHE_ENA(1); 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_FLUSH_AND_INV || 163bf215546Sopenharmony_ci (rctx->b.gfx_level == R600 && rctx->b.flags & R600_CONTEXT_STREAMOUT_FLUSH)) { 164bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 165bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_INV_CONST_CACHE) { 169bf215546Sopenharmony_ci /* Direct constant addressing uses the shader cache. 170bf215546Sopenharmony_ci * Indirect contant addressing uses the vertex cache. */ 171bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_SH_ACTION_ENA(1) | 172bf215546Sopenharmony_ci (rctx->has_vertex_cache ? S_0085F0_VC_ACTION_ENA(1) 173bf215546Sopenharmony_ci : S_0085F0_TC_ACTION_ENA(1)); 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_INV_VERTEX_CACHE) { 176bf215546Sopenharmony_ci cp_coher_cntl |= rctx->has_vertex_cache ? S_0085F0_VC_ACTION_ENA(1) 177bf215546Sopenharmony_ci : S_0085F0_TC_ACTION_ENA(1); 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_INV_TEX_CACHE) { 180bf215546Sopenharmony_ci /* Textures use the texture cache. 181bf215546Sopenharmony_ci * Texture buffer objects use the vertex cache. */ 182bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_TC_ACTION_ENA(1) | 183bf215546Sopenharmony_ci (rctx->has_vertex_cache ? S_0085F0_VC_ACTION_ENA(1) : 0); 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /* Don't use the DB CP COHER logic on r6xx. 187bf215546Sopenharmony_ci * There are hw bugs. 188bf215546Sopenharmony_ci */ 189bf215546Sopenharmony_ci if (rctx->b.gfx_level >= R700 && 190bf215546Sopenharmony_ci (rctx->b.flags & R600_CONTEXT_FLUSH_AND_INV_DB)) { 191bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_DB_ACTION_ENA(1) | 192bf215546Sopenharmony_ci S_0085F0_DB_DEST_BASE_ENA(1) | 193bf215546Sopenharmony_ci S_0085F0_SMX_ACTION_ENA(1); 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci /* Don't use the CB CP COHER logic on r6xx. 197bf215546Sopenharmony_ci * There are hw bugs. 198bf215546Sopenharmony_ci */ 199bf215546Sopenharmony_ci if (rctx->b.gfx_level >= R700 && 200bf215546Sopenharmony_ci (rctx->b.flags & R600_CONTEXT_FLUSH_AND_INV_CB)) { 201bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_CB_ACTION_ENA(1) | 202bf215546Sopenharmony_ci S_0085F0_CB0_DEST_BASE_ENA(1) | 203bf215546Sopenharmony_ci S_0085F0_CB1_DEST_BASE_ENA(1) | 204bf215546Sopenharmony_ci S_0085F0_CB2_DEST_BASE_ENA(1) | 205bf215546Sopenharmony_ci S_0085F0_CB3_DEST_BASE_ENA(1) | 206bf215546Sopenharmony_ci S_0085F0_CB4_DEST_BASE_ENA(1) | 207bf215546Sopenharmony_ci S_0085F0_CB5_DEST_BASE_ENA(1) | 208bf215546Sopenharmony_ci S_0085F0_CB6_DEST_BASE_ENA(1) | 209bf215546Sopenharmony_ci S_0085F0_CB7_DEST_BASE_ENA(1) | 210bf215546Sopenharmony_ci S_0085F0_SMX_ACTION_ENA(1); 211bf215546Sopenharmony_ci if (rctx->b.gfx_level >= EVERGREEN) 212bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_CB8_DEST_BASE_ENA(1) | 213bf215546Sopenharmony_ci S_0085F0_CB9_DEST_BASE_ENA(1) | 214bf215546Sopenharmony_ci S_0085F0_CB10_DEST_BASE_ENA(1) | 215bf215546Sopenharmony_ci S_0085F0_CB11_DEST_BASE_ENA(1); 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci if (rctx->b.gfx_level >= R700 && 219bf215546Sopenharmony_ci rctx->b.flags & R600_CONTEXT_STREAMOUT_FLUSH) { 220bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_SO0_DEST_BASE_ENA(1) | 221bf215546Sopenharmony_ci S_0085F0_SO1_DEST_BASE_ENA(1) | 222bf215546Sopenharmony_ci S_0085F0_SO2_DEST_BASE_ENA(1) | 223bf215546Sopenharmony_ci S_0085F0_SO3_DEST_BASE_ENA(1) | 224bf215546Sopenharmony_ci S_0085F0_SMX_ACTION_ENA(1); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci /* Workaround for buggy flushing on some R6xx chipsets. */ 228bf215546Sopenharmony_ci if ((rctx->b.flags & (R600_CONTEXT_FLUSH_AND_INV | 229bf215546Sopenharmony_ci R600_CONTEXT_STREAMOUT_FLUSH)) && 230bf215546Sopenharmony_ci (rctx->b.family == CHIP_RV670 || 231bf215546Sopenharmony_ci rctx->b.family == CHIP_RS780 || 232bf215546Sopenharmony_ci rctx->b.family == CHIP_RS880)) { 233bf215546Sopenharmony_ci cp_coher_cntl |= S_0085F0_CB1_DEST_BASE_ENA(1) | 234bf215546Sopenharmony_ci S_0085F0_DEST_BASE_0_ENA(1); 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci if (cp_coher_cntl) { 238bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_SURFACE_SYNC, 3, 0)); 239bf215546Sopenharmony_ci radeon_emit(cs, cp_coher_cntl); /* CP_COHER_CNTL */ 240bf215546Sopenharmony_ci radeon_emit(cs, 0xffffffff); /* CP_COHER_SIZE */ 241bf215546Sopenharmony_ci radeon_emit(cs, 0); /* CP_COHER_BASE */ 242bf215546Sopenharmony_ci radeon_emit(cs, 0x0000000A); /* POLL_INTERVAL */ 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci if (rctx->b.flags & R600_CONTEXT_START_PIPELINE_STATS) { 246bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 247bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_PIPELINESTAT_START) | 248bf215546Sopenharmony_ci EVENT_INDEX(0)); 249bf215546Sopenharmony_ci } else if (rctx->b.flags & R600_CONTEXT_STOP_PIPELINE_STATS) { 250bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 251bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_PIPELINESTAT_STOP) | 252bf215546Sopenharmony_ci EVENT_INDEX(0)); 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci /* everything is properly flushed */ 256bf215546Sopenharmony_ci rctx->b.flags = 0; 257bf215546Sopenharmony_ci} 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_civoid r600_context_gfx_flush(void *context, unsigned flags, 260bf215546Sopenharmony_ci struct pipe_fence_handle **fence) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci struct r600_context *ctx = context; 263bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &ctx->b.gfx.cs; 264bf215546Sopenharmony_ci struct radeon_winsys *ws = ctx->b.ws; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size)) 267bf215546Sopenharmony_ci return; 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci if (r600_check_device_reset(&ctx->b)) 270bf215546Sopenharmony_ci return; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci r600_preflush_suspend_features(&ctx->b); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci /* flush the framebuffer cache */ 275bf215546Sopenharmony_ci ctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV | 276bf215546Sopenharmony_ci R600_CONTEXT_FLUSH_AND_INV_CB | 277bf215546Sopenharmony_ci R600_CONTEXT_FLUSH_AND_INV_DB | 278bf215546Sopenharmony_ci R600_CONTEXT_FLUSH_AND_INV_CB_META | 279bf215546Sopenharmony_ci R600_CONTEXT_FLUSH_AND_INV_DB_META | 280bf215546Sopenharmony_ci R600_CONTEXT_WAIT_3D_IDLE | 281bf215546Sopenharmony_ci R600_CONTEXT_WAIT_CP_DMA_IDLE; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci r600_flush_emit(ctx); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (ctx->trace_buf) 286bf215546Sopenharmony_ci eg_trace_emit(ctx); 287bf215546Sopenharmony_ci /* old kernels and userspace don't set SX_MISC, so we must reset it to 0 here */ 288bf215546Sopenharmony_ci if (ctx->b.gfx_level == R600) { 289bf215546Sopenharmony_ci radeon_set_context_reg(cs, R_028350_SX_MISC, 0); 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (ctx->is_debug) { 293bf215546Sopenharmony_ci /* Save the IB for debug contexts. */ 294bf215546Sopenharmony_ci radeon_clear_saved_cs(&ctx->last_gfx); 295bf215546Sopenharmony_ci radeon_save_cs(ws, cs, &ctx->last_gfx, true); 296bf215546Sopenharmony_ci r600_resource_reference(&ctx->last_trace_buf, ctx->trace_buf); 297bf215546Sopenharmony_ci r600_resource_reference(&ctx->trace_buf, NULL); 298bf215546Sopenharmony_ci } 299bf215546Sopenharmony_ci /* Flush the CS. */ 300bf215546Sopenharmony_ci ws->cs_flush(cs, flags, &ctx->b.last_gfx_fence); 301bf215546Sopenharmony_ci if (fence) 302bf215546Sopenharmony_ci ws->fence_reference(fence, ctx->b.last_gfx_fence); 303bf215546Sopenharmony_ci ctx->b.num_gfx_cs_flushes++; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci if (ctx->is_debug) { 306bf215546Sopenharmony_ci if (!ws->fence_wait(ws, ctx->b.last_gfx_fence, 10000000)) { 307bf215546Sopenharmony_ci const char *fname = getenv("R600_TRACE"); 308bf215546Sopenharmony_ci if (!fname) 309bf215546Sopenharmony_ci exit(-1); 310bf215546Sopenharmony_ci FILE *fl = fopen(fname, "w+"); 311bf215546Sopenharmony_ci if (fl) { 312bf215546Sopenharmony_ci eg_dump_debug_state(&ctx->b.b, fl, 0); 313bf215546Sopenharmony_ci fclose(fl); 314bf215546Sopenharmony_ci } else 315bf215546Sopenharmony_ci perror(fname); 316bf215546Sopenharmony_ci exit(-1); 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci r600_begin_new_cs(ctx); 320bf215546Sopenharmony_ci} 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_civoid r600_begin_new_cs(struct r600_context *ctx) 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci unsigned shader; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci if (ctx->is_debug) { 327bf215546Sopenharmony_ci uint32_t zero = 0; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci /* Create a buffer used for writing trace IDs and initialize it to 0. */ 330bf215546Sopenharmony_ci assert(!ctx->trace_buf); 331bf215546Sopenharmony_ci ctx->trace_buf = (struct r600_resource*) 332bf215546Sopenharmony_ci pipe_buffer_create(ctx->b.b.screen, 0, 333bf215546Sopenharmony_ci PIPE_USAGE_STAGING, 4); 334bf215546Sopenharmony_ci if (ctx->trace_buf) 335bf215546Sopenharmony_ci pipe_buffer_write_nooverlap(&ctx->b.b, &ctx->trace_buf->b.b, 336bf215546Sopenharmony_ci 0, sizeof(zero), &zero); 337bf215546Sopenharmony_ci ctx->trace_id = 0; 338bf215546Sopenharmony_ci } 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci if (ctx->trace_buf) 341bf215546Sopenharmony_ci eg_trace_emit(ctx); 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci ctx->b.flags = 0; 344bf215546Sopenharmony_ci ctx->b.gtt = 0; 345bf215546Sopenharmony_ci ctx->b.vram = 0; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci /* Begin a new CS. */ 348bf215546Sopenharmony_ci r600_emit_command_buffer(&ctx->b.gfx.cs, &ctx->start_cs_cmd); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci /* Re-emit states. */ 351bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->alphatest_state.atom); 352bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->blend_color.atom); 353bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->cb_misc_state.atom); 354bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->clip_misc_state.atom); 355bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->clip_state.atom); 356bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->db_misc_state.atom); 357bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->db_state.atom); 358bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->framebuffer.atom); 359bf215546Sopenharmony_ci if (ctx->b.gfx_level >= EVERGREEN) { 360bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->fragment_images.atom); 361bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->fragment_buffers.atom); 362bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->compute_images.atom); 363bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->compute_buffers.atom); 364bf215546Sopenharmony_ci } 365bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_PS].atom); 366bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->poly_offset_state.atom); 367bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->vgt_state.atom); 368bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->sample_mask.atom); 369bf215546Sopenharmony_ci ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; 370bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->b.scissors.atom); 371bf215546Sopenharmony_ci ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; 372bf215546Sopenharmony_ci ctx->b.viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1; 373bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->b.viewports.atom); 374bf215546Sopenharmony_ci if (ctx->b.gfx_level <= EVERGREEN) { 375bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->config_state.atom); 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->stencil_ref.atom); 378bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->vertex_fetch_shader.atom); 379bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_ES].atom); 380bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->shader_stages.atom); 381bf215546Sopenharmony_ci if (ctx->gs_shader) { 382bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_GS].atom); 383bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->gs_rings.atom); 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci if (ctx->tes_shader) { 386bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[EG_HW_STAGE_HS].atom); 387bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[EG_HW_STAGE_LS].atom); 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->hw_shader_stages[R600_HW_STAGE_VS].atom); 390bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->b.streamout.enable_atom); 391bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->b.render_cond_atom); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci if (ctx->blend_state.cso) 394bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->blend_state.atom); 395bf215546Sopenharmony_ci if (ctx->dsa_state.cso) 396bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->dsa_state.atom); 397bf215546Sopenharmony_ci if (ctx->rasterizer_state.cso) 398bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->rasterizer_state.atom); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci if (ctx->b.gfx_level <= R700) { 401bf215546Sopenharmony_ci r600_mark_atom_dirty(ctx, &ctx->seamless_cube_map.atom); 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci ctx->vertex_buffer_state.dirty_mask = ctx->vertex_buffer_state.enabled_mask; 405bf215546Sopenharmony_ci r600_vertex_buffers_dirty(ctx); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci /* Re-emit shader resources. */ 408bf215546Sopenharmony_ci for (shader = 0; shader < PIPE_SHADER_TYPES; shader++) { 409bf215546Sopenharmony_ci struct r600_constbuf_state *constbuf = &ctx->constbuf_state[shader]; 410bf215546Sopenharmony_ci struct r600_textures_info *samplers = &ctx->samplers[shader]; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci constbuf->dirty_mask = constbuf->enabled_mask; 413bf215546Sopenharmony_ci samplers->views.dirty_mask = samplers->views.enabled_mask; 414bf215546Sopenharmony_ci samplers->states.dirty_mask = samplers->states.enabled_mask; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci r600_constant_buffers_dirty(ctx, constbuf); 417bf215546Sopenharmony_ci r600_sampler_views_dirty(ctx, &samplers->views); 418bf215546Sopenharmony_ci r600_sampler_states_dirty(ctx, &samplers->states); 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci for (shader = 0; shader < ARRAY_SIZE(ctx->scratch_buffers); shader++) { 422bf215546Sopenharmony_ci ctx->scratch_buffers[shader].dirty = true; 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci r600_postflush_resume_features(&ctx->b); 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci /* Re-emit the draw state. */ 428bf215546Sopenharmony_ci ctx->last_primitive_type = -1; 429bf215546Sopenharmony_ci ctx->last_start_instance = -1; 430bf215546Sopenharmony_ci ctx->last_rast_prim = -1; 431bf215546Sopenharmony_ci ctx->current_rast_prim = -1; 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci assert(!ctx->b.gfx.cs.prev_dw); 434bf215546Sopenharmony_ci ctx->b.initial_gfx_cs_size = ctx->b.gfx.cs.current.cdw; 435bf215546Sopenharmony_ci} 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_civoid r600_emit_pfp_sync_me(struct r600_context *rctx) 438bf215546Sopenharmony_ci{ 439bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->b.gfx.cs; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci if (rctx->b.gfx_level >= EVERGREEN) { 442bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0)); 443bf215546Sopenharmony_ci radeon_emit(cs, 0); 444bf215546Sopenharmony_ci } else { 445bf215546Sopenharmony_ci /* Emulate PFP_SYNC_ME by writing a value to memory in ME and 446bf215546Sopenharmony_ci * waiting for it in PFP. 447bf215546Sopenharmony_ci */ 448bf215546Sopenharmony_ci struct r600_resource *buf = NULL; 449bf215546Sopenharmony_ci unsigned offset, reloc; 450bf215546Sopenharmony_ci uint64_t va; 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci /* 16-byte address alignment is required by WAIT_REG_MEM. */ 453bf215546Sopenharmony_ci u_suballocator_alloc(&rctx->b.allocator_zeroed_memory, 4, 16, 454bf215546Sopenharmony_ci &offset, (struct pipe_resource**)&buf); 455bf215546Sopenharmony_ci if (!buf) { 456bf215546Sopenharmony_ci /* This is too heavyweight, but will work. */ 457bf215546Sopenharmony_ci rctx->b.gfx.flush(rctx, PIPE_FLUSH_ASYNC, NULL); 458bf215546Sopenharmony_ci return; 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci reloc = radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, buf, 462bf215546Sopenharmony_ci RADEON_USAGE_READWRITE | 463bf215546Sopenharmony_ci RADEON_PRIO_FENCE_TRACE); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci va = buf->gpu_address + offset; 466bf215546Sopenharmony_ci assert(va % 16 == 0); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci /* Write 1 to memory in ME. */ 469bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_MEM_WRITE, 3, 0)); 470bf215546Sopenharmony_ci radeon_emit(cs, va); 471bf215546Sopenharmony_ci radeon_emit(cs, ((va >> 32) & 0xff) | MEM_WRITE_32_BITS); 472bf215546Sopenharmony_ci radeon_emit(cs, 1); 473bf215546Sopenharmony_ci radeon_emit(cs, 0); 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); 476bf215546Sopenharmony_ci radeon_emit(cs, reloc); 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci /* Wait in PFP (PFP can only do GEQUAL against memory). */ 479bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_WAIT_REG_MEM, 5, 0)); 480bf215546Sopenharmony_ci radeon_emit(cs, WAIT_REG_MEM_GEQUAL | 481bf215546Sopenharmony_ci WAIT_REG_MEM_MEMORY | 482bf215546Sopenharmony_ci WAIT_REG_MEM_PFP); 483bf215546Sopenharmony_ci radeon_emit(cs, va); 484bf215546Sopenharmony_ci radeon_emit(cs, va >> 32); 485bf215546Sopenharmony_ci radeon_emit(cs, 1); /* reference value */ 486bf215546Sopenharmony_ci radeon_emit(cs, 0xffffffff); /* mask */ 487bf215546Sopenharmony_ci radeon_emit(cs, 4); /* poll interval */ 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); 490bf215546Sopenharmony_ci radeon_emit(cs, reloc); 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci r600_resource_reference(&buf, NULL); 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci/* The max number of bytes to copy per packet. */ 497bf215546Sopenharmony_ci#define CP_DMA_MAX_BYTE_COUNT ((1 << 21) - 8) 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_civoid r600_cp_dma_copy_buffer(struct r600_context *rctx, 500bf215546Sopenharmony_ci struct pipe_resource *dst, uint64_t dst_offset, 501bf215546Sopenharmony_ci struct pipe_resource *src, uint64_t src_offset, 502bf215546Sopenharmony_ci unsigned size) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->b.gfx.cs; 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci assert(size); 507bf215546Sopenharmony_ci assert(rctx->screen->b.has_cp_dma); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci /* Mark the buffer range of destination as valid (initialized), 510bf215546Sopenharmony_ci * so that transfer_map knows it should wait for the GPU when mapping 511bf215546Sopenharmony_ci * that range. */ 512bf215546Sopenharmony_ci util_range_add(dst, &r600_resource(dst)->valid_buffer_range, dst_offset, 513bf215546Sopenharmony_ci dst_offset + size); 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci dst_offset += r600_resource(dst)->gpu_address; 516bf215546Sopenharmony_ci src_offset += r600_resource(src)->gpu_address; 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci /* Flush the caches where the resources are bound. */ 519bf215546Sopenharmony_ci rctx->b.flags |= r600_get_flush_flags(R600_COHERENCY_SHADER) | 520bf215546Sopenharmony_ci R600_CONTEXT_WAIT_3D_IDLE; 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci /* There are differences between R700 and EG in CP DMA, 523bf215546Sopenharmony_ci * but we only use the common bits here. */ 524bf215546Sopenharmony_ci while (size) { 525bf215546Sopenharmony_ci unsigned sync = 0; 526bf215546Sopenharmony_ci unsigned byte_count = MIN2(size, CP_DMA_MAX_BYTE_COUNT); 527bf215546Sopenharmony_ci unsigned src_reloc, dst_reloc; 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci r600_need_cs_space(rctx, 530bf215546Sopenharmony_ci 10 + (rctx->b.flags ? R600_MAX_FLUSH_CS_DWORDS : 0) + 531bf215546Sopenharmony_ci 3 + R600_MAX_PFP_SYNC_ME_DWORDS, FALSE, 0); 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci /* Flush the caches for the first copy only. */ 534bf215546Sopenharmony_ci if (rctx->b.flags) { 535bf215546Sopenharmony_ci r600_flush_emit(rctx); 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci /* Do the synchronization after the last copy, so that all data is written to memory. */ 539bf215546Sopenharmony_ci if (size == byte_count) { 540bf215546Sopenharmony_ci sync = PKT3_CP_DMA_CP_SYNC; 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci /* This must be done after r600_need_cs_space. */ 544bf215546Sopenharmony_ci src_reloc = radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, (struct r600_resource*)src, 545bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_PRIO_CP_DMA); 546bf215546Sopenharmony_ci dst_reloc = radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, (struct r600_resource*)dst, 547bf215546Sopenharmony_ci RADEON_USAGE_WRITE | RADEON_PRIO_CP_DMA); 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_CP_DMA, 4, 0)); 550bf215546Sopenharmony_ci radeon_emit(cs, src_offset); /* SRC_ADDR_LO [31:0] */ 551bf215546Sopenharmony_ci radeon_emit(cs, sync | ((src_offset >> 32) & 0xff)); /* CP_SYNC [31] | SRC_ADDR_HI [7:0] */ 552bf215546Sopenharmony_ci radeon_emit(cs, dst_offset); /* DST_ADDR_LO [31:0] */ 553bf215546Sopenharmony_ci radeon_emit(cs, (dst_offset >> 32) & 0xff); /* DST_ADDR_HI [7:0] */ 554bf215546Sopenharmony_ci radeon_emit(cs, byte_count); /* COMMAND [29:22] | BYTE_COUNT [20:0] */ 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); 557bf215546Sopenharmony_ci radeon_emit(cs, src_reloc); 558bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); 559bf215546Sopenharmony_ci radeon_emit(cs, dst_reloc); 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci size -= byte_count; 562bf215546Sopenharmony_ci src_offset += byte_count; 563bf215546Sopenharmony_ci dst_offset += byte_count; 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci /* CP_DMA_CP_SYNC doesn't wait for idle on R6xx, but this does. */ 567bf215546Sopenharmony_ci if (rctx->b.gfx_level == R600) 568bf215546Sopenharmony_ci radeon_set_config_reg(cs, R_008040_WAIT_UNTIL, 569bf215546Sopenharmony_ci S_008040_WAIT_CP_DMA_IDLE(1)); 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci /* CP DMA is executed in ME, but index buffers are read by PFP. 572bf215546Sopenharmony_ci * This ensures that ME (CP DMA) is idle before PFP starts fetching 573bf215546Sopenharmony_ci * indices. If we wanted to execute CP DMA in PFP, this packet 574bf215546Sopenharmony_ci * should precede it. 575bf215546Sopenharmony_ci */ 576bf215546Sopenharmony_ci r600_emit_pfp_sync_me(rctx); 577bf215546Sopenharmony_ci} 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_civoid r600_dma_copy_buffer(struct r600_context *rctx, 580bf215546Sopenharmony_ci struct pipe_resource *dst, 581bf215546Sopenharmony_ci struct pipe_resource *src, 582bf215546Sopenharmony_ci uint64_t dst_offset, 583bf215546Sopenharmony_ci uint64_t src_offset, 584bf215546Sopenharmony_ci uint64_t size) 585bf215546Sopenharmony_ci{ 586bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->b.dma.cs; 587bf215546Sopenharmony_ci unsigned i, ncopy, csize; 588bf215546Sopenharmony_ci struct r600_resource *rdst = (struct r600_resource*)dst; 589bf215546Sopenharmony_ci struct r600_resource *rsrc = (struct r600_resource*)src; 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci /* Mark the buffer range of destination as valid (initialized), 592bf215546Sopenharmony_ci * so that transfer_map knows it should wait for the GPU when mapping 593bf215546Sopenharmony_ci * that range. */ 594bf215546Sopenharmony_ci util_range_add(&rdst->b.b, &rdst->valid_buffer_range, dst_offset, 595bf215546Sopenharmony_ci dst_offset + size); 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci size >>= 2; /* convert to dwords */ 598bf215546Sopenharmony_ci ncopy = (size / R600_DMA_COPY_MAX_SIZE_DW) + !!(size % R600_DMA_COPY_MAX_SIZE_DW); 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci r600_need_dma_space(&rctx->b, ncopy * 5, rdst, rsrc); 601bf215546Sopenharmony_ci for (i = 0; i < ncopy; i++) { 602bf215546Sopenharmony_ci csize = size < R600_DMA_COPY_MAX_SIZE_DW ? size : R600_DMA_COPY_MAX_SIZE_DW; 603bf215546Sopenharmony_ci /* emit reloc before writing cs so that cs is always in consistent state */ 604bf215546Sopenharmony_ci radeon_add_to_buffer_list(&rctx->b, &rctx->b.dma, rsrc, RADEON_USAGE_READ); 605bf215546Sopenharmony_ci radeon_add_to_buffer_list(&rctx->b, &rctx->b.dma, rdst, RADEON_USAGE_WRITE); 606bf215546Sopenharmony_ci radeon_emit(cs, DMA_PACKET(DMA_PACKET_COPY, 0, 0, csize)); 607bf215546Sopenharmony_ci radeon_emit(cs, dst_offset & 0xfffffffc); 608bf215546Sopenharmony_ci radeon_emit(cs, src_offset & 0xfffffffc); 609bf215546Sopenharmony_ci radeon_emit(cs, (dst_offset >> 32UL) & 0xff); 610bf215546Sopenharmony_ci radeon_emit(cs, (src_offset >> 32UL) & 0xff); 611bf215546Sopenharmony_ci dst_offset += csize << 2; 612bf215546Sopenharmony_ci src_offset += csize << 2; 613bf215546Sopenharmony_ci size -= csize; 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci} 616