1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2013 Advanced Micro Devices, Inc. 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * 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 NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: Marek Olšák <maraeo@gmail.com> 24bf215546Sopenharmony_ci * 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "r600_pipe_common.h" 28bf215546Sopenharmony_ci#include "r600_cs.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "util/u_memory.h" 31bf215546Sopenharmony_ci#include "evergreend.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#define R_008490_CP_STRMOUT_CNTL 0x008490 34bf215546Sopenharmony_ci#define R_028AB0_VGT_STRMOUT_EN 0x028AB0 35bf215546Sopenharmony_ci#define R_028B20_VGT_STRMOUT_BUFFER_EN 0x028B20 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic void r600_set_streamout_enable(struct r600_common_context *rctx, bool enable); 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_cistatic struct pipe_stream_output_target * 40bf215546Sopenharmony_cir600_create_so_target(struct pipe_context *ctx, 41bf215546Sopenharmony_ci struct pipe_resource *buffer, 42bf215546Sopenharmony_ci unsigned buffer_offset, 43bf215546Sopenharmony_ci unsigned buffer_size) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci struct r600_common_context *rctx = (struct r600_common_context *)ctx; 46bf215546Sopenharmony_ci struct r600_so_target *t; 47bf215546Sopenharmony_ci struct r600_resource *rbuffer = (struct r600_resource*)buffer; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci t = CALLOC_STRUCT(r600_so_target); 50bf215546Sopenharmony_ci if (!t) { 51bf215546Sopenharmony_ci return NULL; 52bf215546Sopenharmony_ci } 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci u_suballocator_alloc(&rctx->allocator_zeroed_memory, 4, 4, 55bf215546Sopenharmony_ci &t->buf_filled_size_offset, 56bf215546Sopenharmony_ci (struct pipe_resource**)&t->buf_filled_size); 57bf215546Sopenharmony_ci if (!t->buf_filled_size) { 58bf215546Sopenharmony_ci FREE(t); 59bf215546Sopenharmony_ci return NULL; 60bf215546Sopenharmony_ci } 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci t->b.reference.count = 1; 63bf215546Sopenharmony_ci t->b.context = ctx; 64bf215546Sopenharmony_ci pipe_resource_reference(&t->b.buffer, buffer); 65bf215546Sopenharmony_ci t->b.buffer_offset = buffer_offset; 66bf215546Sopenharmony_ci t->b.buffer_size = buffer_size; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci util_range_add(buffer, &rbuffer->valid_buffer_range, buffer_offset, 69bf215546Sopenharmony_ci buffer_offset + buffer_size); 70bf215546Sopenharmony_ci return &t->b; 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic void r600_so_target_destroy(struct pipe_context *ctx, 74bf215546Sopenharmony_ci struct pipe_stream_output_target *target) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct r600_so_target *t = (struct r600_so_target*)target; 77bf215546Sopenharmony_ci pipe_resource_reference(&t->b.buffer, NULL); 78bf215546Sopenharmony_ci r600_resource_reference(&t->buf_filled_size, NULL); 79bf215546Sopenharmony_ci FREE(t); 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_civoid r600_streamout_buffers_dirty(struct r600_common_context *rctx) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci struct r600_atom *begin = &rctx->streamout.begin_atom; 85bf215546Sopenharmony_ci unsigned num_bufs = util_bitcount(rctx->streamout.enabled_mask); 86bf215546Sopenharmony_ci unsigned num_bufs_appended = util_bitcount(rctx->streamout.enabled_mask & 87bf215546Sopenharmony_ci rctx->streamout.append_bitmask); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci if (!num_bufs) 90bf215546Sopenharmony_ci return; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci rctx->streamout.num_dw_for_end = 93bf215546Sopenharmony_ci 12 + /* flush_vgt_streamout */ 94bf215546Sopenharmony_ci num_bufs * 11; /* STRMOUT_BUFFER_UPDATE, BUFFER_SIZE */ 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci begin->num_dw = 12; /* flush_vgt_streamout */ 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci begin->num_dw += num_bufs * 7; /* SET_CONTEXT_REG */ 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci if (rctx->family >= CHIP_RS780 && rctx->family <= CHIP_RV740) 101bf215546Sopenharmony_ci begin->num_dw += num_bufs * 5; /* STRMOUT_BASE_UPDATE */ 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci begin->num_dw += 104bf215546Sopenharmony_ci num_bufs_appended * 8 + /* STRMOUT_BUFFER_UPDATE */ 105bf215546Sopenharmony_ci (num_bufs - num_bufs_appended) * 6 + /* STRMOUT_BUFFER_UPDATE */ 106bf215546Sopenharmony_ci (rctx->family > CHIP_R600 && rctx->family < CHIP_RS780 ? 2 : 0); /* SURFACE_BASE_UPDATE */ 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci rctx->set_atom_dirty(rctx, begin, true); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci r600_set_streamout_enable(rctx, true); 111bf215546Sopenharmony_ci} 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_civoid r600_set_streamout_targets(struct pipe_context *ctx, 114bf215546Sopenharmony_ci unsigned num_targets, 115bf215546Sopenharmony_ci struct pipe_stream_output_target **targets, 116bf215546Sopenharmony_ci const unsigned *offsets) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci struct r600_common_context *rctx = (struct r600_common_context *)ctx; 119bf215546Sopenharmony_ci unsigned i; 120bf215546Sopenharmony_ci unsigned enabled_mask = 0, append_bitmask = 0; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci /* Stop streamout. */ 123bf215546Sopenharmony_ci if (rctx->streamout.num_targets && rctx->streamout.begin_emitted) { 124bf215546Sopenharmony_ci r600_emit_streamout_end(rctx); 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci /* Set the new targets. */ 128bf215546Sopenharmony_ci for (i = 0; i < num_targets; i++) { 129bf215546Sopenharmony_ci pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->streamout.targets[i], targets[i]); 130bf215546Sopenharmony_ci if (!targets[i]) 131bf215546Sopenharmony_ci continue; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci r600_context_add_resource_size(ctx, targets[i]->buffer); 134bf215546Sopenharmony_ci enabled_mask |= 1 << i; 135bf215546Sopenharmony_ci if (offsets[i] == ((unsigned)-1)) 136bf215546Sopenharmony_ci append_bitmask |= 1 << i; 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci for (; i < rctx->streamout.num_targets; i++) { 139bf215546Sopenharmony_ci pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->streamout.targets[i], NULL); 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci rctx->streamout.enabled_mask = enabled_mask; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci rctx->streamout.num_targets = num_targets; 145bf215546Sopenharmony_ci rctx->streamout.append_bitmask = append_bitmask; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (num_targets) { 148bf215546Sopenharmony_ci r600_streamout_buffers_dirty(rctx); 149bf215546Sopenharmony_ci } else { 150bf215546Sopenharmony_ci rctx->set_atom_dirty(rctx, &rctx->streamout.begin_atom, false); 151bf215546Sopenharmony_ci r600_set_streamout_enable(rctx, false); 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci} 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_cistatic void r600_flush_vgt_streamout(struct r600_common_context *rctx) 156bf215546Sopenharmony_ci{ 157bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->gfx.cs; 158bf215546Sopenharmony_ci unsigned reg_strmout_cntl; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci /* The register is at different places on different ASICs. */ 161bf215546Sopenharmony_ci if (rctx->gfx_level >= EVERGREEN) { 162bf215546Sopenharmony_ci reg_strmout_cntl = R_0084FC_CP_STRMOUT_CNTL; 163bf215546Sopenharmony_ci } else { 164bf215546Sopenharmony_ci reg_strmout_cntl = R_008490_CP_STRMOUT_CNTL; 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci radeon_set_config_reg(cs, reg_strmout_cntl, 0); 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 170bf215546Sopenharmony_ci radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SO_VGTSTREAMOUT_FLUSH) | EVENT_INDEX(0)); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_WAIT_REG_MEM, 5, 0)); 173bf215546Sopenharmony_ci radeon_emit(cs, WAIT_REG_MEM_EQUAL); /* wait until the register is equal to the reference value */ 174bf215546Sopenharmony_ci radeon_emit(cs, reg_strmout_cntl >> 2); /* register */ 175bf215546Sopenharmony_ci radeon_emit(cs, 0); 176bf215546Sopenharmony_ci radeon_emit(cs, S_0084FC_OFFSET_UPDATE_DONE(1)); /* reference value */ 177bf215546Sopenharmony_ci radeon_emit(cs, S_0084FC_OFFSET_UPDATE_DONE(1)); /* mask */ 178bf215546Sopenharmony_ci radeon_emit(cs, 4); /* poll interval */ 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cistatic void r600_emit_streamout_begin(struct r600_common_context *rctx, struct r600_atom *atom) 182bf215546Sopenharmony_ci{ 183bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->gfx.cs; 184bf215546Sopenharmony_ci struct r600_so_target **t = rctx->streamout.targets; 185bf215546Sopenharmony_ci uint16_t *stride_in_dw = rctx->streamout.stride_in_dw; 186bf215546Sopenharmony_ci unsigned i, update_flags = 0; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci r600_flush_vgt_streamout(rctx); 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci for (i = 0; i < rctx->streamout.num_targets; i++) { 191bf215546Sopenharmony_ci if (!t[i]) 192bf215546Sopenharmony_ci continue; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci t[i]->stride_in_dw = stride_in_dw[i]; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci uint64_t va = r600_resource(t[i]->b.buffer)->gpu_address; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci update_flags |= SURFACE_BASE_UPDATE_STRMOUT(i); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci radeon_set_context_reg_seq(cs, R_028AD0_VGT_STRMOUT_BUFFER_SIZE_0 + 16*i, 3); 201bf215546Sopenharmony_ci radeon_emit(cs, (t[i]->b.buffer_offset + 202bf215546Sopenharmony_ci t[i]->b.buffer_size) >> 2); /* BUFFER_SIZE (in DW) */ 203bf215546Sopenharmony_ci radeon_emit(cs, stride_in_dw[i]); /* VTX_STRIDE (in DW) */ 204bf215546Sopenharmony_ci radeon_emit(cs, va >> 8); /* BUFFER_BASE */ 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci r600_emit_reloc(rctx, &rctx->gfx, r600_resource(t[i]->b.buffer), 207bf215546Sopenharmony_ci RADEON_USAGE_WRITE | RADEON_PRIO_SHADER_RW_BUFFER); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci /* R7xx requires this packet after updating BUFFER_BASE. 210bf215546Sopenharmony_ci * Without this, R7xx locks up. */ 211bf215546Sopenharmony_ci if (rctx->family >= CHIP_RS780 && rctx->family <= CHIP_RV740) { 212bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_STRMOUT_BASE_UPDATE, 1, 0)); 213bf215546Sopenharmony_ci radeon_emit(cs, i); 214bf215546Sopenharmony_ci radeon_emit(cs, va >> 8); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci r600_emit_reloc(rctx, &rctx->gfx, r600_resource(t[i]->b.buffer), 217bf215546Sopenharmony_ci RADEON_USAGE_WRITE | RADEON_PRIO_SHADER_RW_BUFFER); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci if (rctx->streamout.append_bitmask & (1 << i) && t[i]->buf_filled_size_valid) { 221bf215546Sopenharmony_ci uint64_t va = t[i]->buf_filled_size->gpu_address + 222bf215546Sopenharmony_ci t[i]->buf_filled_size_offset; 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci /* Append. */ 225bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0)); 226bf215546Sopenharmony_ci radeon_emit(cs, STRMOUT_SELECT_BUFFER(i) | 227bf215546Sopenharmony_ci STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_FROM_MEM)); /* control */ 228bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 229bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 230bf215546Sopenharmony_ci radeon_emit(cs, va); /* src address lo */ 231bf215546Sopenharmony_ci radeon_emit(cs, va >> 32); /* src address hi */ 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci r600_emit_reloc(rctx, &rctx->gfx, t[i]->buf_filled_size, 234bf215546Sopenharmony_ci RADEON_USAGE_READ | RADEON_PRIO_SO_FILLED_SIZE); 235bf215546Sopenharmony_ci } else { 236bf215546Sopenharmony_ci /* Start from the beginning. */ 237bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0)); 238bf215546Sopenharmony_ci radeon_emit(cs, STRMOUT_SELECT_BUFFER(i) | 239bf215546Sopenharmony_ci STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_FROM_PACKET)); /* control */ 240bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 241bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 242bf215546Sopenharmony_ci radeon_emit(cs, t[i]->b.buffer_offset >> 2); /* buffer offset in DW */ 243bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if (rctx->family > CHIP_R600 && rctx->family < CHIP_RV770) { 248bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_SURFACE_BASE_UPDATE, 0, 0)); 249bf215546Sopenharmony_ci radeon_emit(cs, update_flags); 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci rctx->streamout.begin_emitted = true; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_civoid r600_emit_streamout_end(struct r600_common_context *rctx) 255bf215546Sopenharmony_ci{ 256bf215546Sopenharmony_ci struct radeon_cmdbuf *cs = &rctx->gfx.cs; 257bf215546Sopenharmony_ci struct r600_so_target **t = rctx->streamout.targets; 258bf215546Sopenharmony_ci unsigned i; 259bf215546Sopenharmony_ci uint64_t va; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci r600_flush_vgt_streamout(rctx); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci for (i = 0; i < rctx->streamout.num_targets; i++) { 264bf215546Sopenharmony_ci if (!t[i]) 265bf215546Sopenharmony_ci continue; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci va = t[i]->buf_filled_size->gpu_address + t[i]->buf_filled_size_offset; 268bf215546Sopenharmony_ci radeon_emit(cs, PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0)); 269bf215546Sopenharmony_ci radeon_emit(cs, STRMOUT_SELECT_BUFFER(i) | 270bf215546Sopenharmony_ci STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_NONE) | 271bf215546Sopenharmony_ci STRMOUT_STORE_BUFFER_FILLED_SIZE); /* control */ 272bf215546Sopenharmony_ci radeon_emit(cs, va); /* dst address lo */ 273bf215546Sopenharmony_ci radeon_emit(cs, va >> 32); /* dst address hi */ 274bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 275bf215546Sopenharmony_ci radeon_emit(cs, 0); /* unused */ 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci r600_emit_reloc(rctx, &rctx->gfx, t[i]->buf_filled_size, 278bf215546Sopenharmony_ci RADEON_USAGE_WRITE | RADEON_PRIO_SO_FILLED_SIZE); 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci /* Zero the buffer size. The counters (primitives generated, 281bf215546Sopenharmony_ci * primitives emitted) may be enabled even if there is not 282bf215546Sopenharmony_ci * buffer bound. This ensures that the primitives-emitted query 283bf215546Sopenharmony_ci * won't increment. */ 284bf215546Sopenharmony_ci radeon_set_context_reg(cs, R_028AD0_VGT_STRMOUT_BUFFER_SIZE_0 + 16*i, 0); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci t[i]->buf_filled_size_valid = true; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci rctx->streamout.begin_emitted = false; 290bf215546Sopenharmony_ci rctx->flags |= R600_CONTEXT_STREAMOUT_FLUSH; 291bf215546Sopenharmony_ci} 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci/* STREAMOUT CONFIG DERIVED STATE 294bf215546Sopenharmony_ci * 295bf215546Sopenharmony_ci * Streamout must be enabled for the PRIMITIVES_GENERATED query to work. 296bf215546Sopenharmony_ci * The buffer mask is an independent state, so no writes occur if there 297bf215546Sopenharmony_ci * are no buffers bound. 298bf215546Sopenharmony_ci */ 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_cistatic void r600_emit_streamout_enable(struct r600_common_context *rctx, 301bf215546Sopenharmony_ci struct r600_atom *atom) 302bf215546Sopenharmony_ci{ 303bf215546Sopenharmony_ci unsigned strmout_config_reg = R_028AB0_VGT_STRMOUT_EN; 304bf215546Sopenharmony_ci unsigned strmout_config_val = S_028B94_STREAMOUT_0_EN(r600_get_strmout_en(rctx)); 305bf215546Sopenharmony_ci unsigned strmout_buffer_reg = R_028B20_VGT_STRMOUT_BUFFER_EN; 306bf215546Sopenharmony_ci unsigned strmout_buffer_val = rctx->streamout.hw_enabled_mask & 307bf215546Sopenharmony_ci rctx->streamout.enabled_stream_buffers_mask; 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci if (rctx->gfx_level >= EVERGREEN) { 310bf215546Sopenharmony_ci strmout_buffer_reg = R_028B98_VGT_STRMOUT_BUFFER_CONFIG; 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci strmout_config_reg = R_028B94_VGT_STRMOUT_CONFIG; 313bf215546Sopenharmony_ci strmout_config_val |= 314bf215546Sopenharmony_ci S_028B94_STREAMOUT_1_EN(r600_get_strmout_en(rctx)) | 315bf215546Sopenharmony_ci S_028B94_STREAMOUT_2_EN(r600_get_strmout_en(rctx)) | 316bf215546Sopenharmony_ci S_028B94_STREAMOUT_3_EN(r600_get_strmout_en(rctx)); 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci radeon_set_context_reg(&rctx->gfx.cs, strmout_buffer_reg, strmout_buffer_val); 319bf215546Sopenharmony_ci radeon_set_context_reg(&rctx->gfx.cs, strmout_config_reg, strmout_config_val); 320bf215546Sopenharmony_ci} 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_cistatic void r600_set_streamout_enable(struct r600_common_context *rctx, bool enable) 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci bool old_strmout_en = r600_get_strmout_en(rctx); 325bf215546Sopenharmony_ci unsigned old_hw_enabled_mask = rctx->streamout.hw_enabled_mask; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci rctx->streamout.streamout_enabled = enable; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci rctx->streamout.hw_enabled_mask = rctx->streamout.enabled_mask | 330bf215546Sopenharmony_ci (rctx->streamout.enabled_mask << 4) | 331bf215546Sopenharmony_ci (rctx->streamout.enabled_mask << 8) | 332bf215546Sopenharmony_ci (rctx->streamout.enabled_mask << 12); 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if ((old_strmout_en != r600_get_strmout_en(rctx)) || 335bf215546Sopenharmony_ci (old_hw_enabled_mask != rctx->streamout.hw_enabled_mask)) { 336bf215546Sopenharmony_ci rctx->set_atom_dirty(rctx, &rctx->streamout.enable_atom, true); 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci} 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_civoid r600_update_prims_generated_query_state(struct r600_common_context *rctx, 341bf215546Sopenharmony_ci unsigned type, int diff) 342bf215546Sopenharmony_ci{ 343bf215546Sopenharmony_ci if (type == PIPE_QUERY_PRIMITIVES_GENERATED) { 344bf215546Sopenharmony_ci bool old_strmout_en = r600_get_strmout_en(rctx); 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci rctx->streamout.num_prims_gen_queries += diff; 347bf215546Sopenharmony_ci assert(rctx->streamout.num_prims_gen_queries >= 0); 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci rctx->streamout.prims_gen_query_enabled = 350bf215546Sopenharmony_ci rctx->streamout.num_prims_gen_queries != 0; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci if (old_strmout_en != r600_get_strmout_en(rctx)) { 353bf215546Sopenharmony_ci rctx->set_atom_dirty(rctx, &rctx->streamout.enable_atom, true); 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci } 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_civoid r600_streamout_init(struct r600_common_context *rctx) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci rctx->b.create_stream_output_target = r600_create_so_target; 361bf215546Sopenharmony_ci rctx->b.stream_output_target_destroy = r600_so_target_destroy; 362bf215546Sopenharmony_ci rctx->streamout.begin_atom.emit = r600_emit_streamout_begin; 363bf215546Sopenharmony_ci rctx->streamout.enable_atom.emit = r600_emit_streamout_enable; 364bf215546Sopenharmony_ci rctx->streamout.enable_atom.num_dw = 6; 365bf215546Sopenharmony_ci} 366