| /* |
| * Copyright 2012 Advanced Micro Devices, Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * on the rights to use, copy, modify, merge, publish, distribute, sub |
| * license, and/or sell copies of the Software, and to permit persons to whom |
| * the Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
| * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * Authors: |
| * Christian König <christian.koenig@amd.com> |
| */ |
| |
| #include "radeonsi_pipe.h" |
| #include "si_state.h" |
| |
| /* |
| * Stream out |
| */ |
| |
| #if 0 |
| void si_context_streamout_begin(struct r600_context *ctx) |
| { |
| struct radeon_winsys_cs *cs = ctx->cs; |
| struct si_so_target **t = ctx->so_targets; |
| unsigned *strides = ctx->vs_shader_so_strides; |
| unsigned buffer_en, i; |
| |
| buffer_en = (ctx->num_so_targets >= 1 && t[0] ? 1 : 0) | |
| (ctx->num_so_targets >= 2 && t[1] ? 2 : 0) | |
| (ctx->num_so_targets >= 3 && t[2] ? 4 : 0) | |
| (ctx->num_so_targets >= 4 && t[3] ? 8 : 0); |
| |
| ctx->num_cs_dw_streamout_end = |
| 12 + /* flush_vgt_streamout */ |
| util_bitcount(buffer_en) * 8 + |
| 3; |
| |
| si_need_cs_space(ctx, |
| 12 + /* flush_vgt_streamout */ |
| 6 + /* enables */ |
| util_bitcount(buffer_en & ctx->streamout_append_bitmask) * 8 + |
| util_bitcount(buffer_en & ~ctx->streamout_append_bitmask) * 6 + |
| ctx->num_cs_dw_streamout_end, TRUE); |
| |
| if (ctx->chip_class >= CAYMAN) { |
| evergreen_flush_vgt_streamout(ctx); |
| evergreen_set_streamout_enable(ctx, buffer_en); |
| } |
| |
| for (i = 0; i < ctx->num_so_targets; i++) { |
| #if 0 |
| if (t[i]) { |
| t[i]->stride = strides[i]; |
| t[i]->so_index = i; |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 3, 0); |
| cs->buf[cs->cdw++] = (R_028AD0_VGT_STRMOUT_BUFFER_SIZE_0 + |
| 16*i - SI_CONTEXT_REG_OFFSET) >> 2; |
| cs->buf[cs->cdw++] = (t[i]->b.buffer_offset + |
| t[i]->b.buffer_size) >> 2; /* BUFFER_SIZE (in DW) */ |
| cs->buf[cs->cdw++] = strides[i] >> 2; /* VTX_STRIDE (in DW) */ |
| cs->buf[cs->cdw++] = 0; /* BUFFER_BASE */ |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0); |
| cs->buf[cs->cdw++] = |
| si_context_bo_reloc(ctx, si_resource(t[i]->b.buffer), |
| RADEON_USAGE_WRITE); |
| |
| if (ctx->streamout_append_bitmask & (1 << i)) { |
| /* Append. */ |
| cs->buf[cs->cdw++] = PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0); |
| cs->buf[cs->cdw++] = STRMOUT_SELECT_BUFFER(i) | |
| STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_FROM_MEM); /* control */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| cs->buf[cs->cdw++] = 0; /* src address lo */ |
| cs->buf[cs->cdw++] = 0; /* src address hi */ |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0); |
| cs->buf[cs->cdw++] = |
| si_context_bo_reloc(ctx, t[i]->filled_size, |
| RADEON_USAGE_READ); |
| } else { |
| /* Start from the beginning. */ |
| cs->buf[cs->cdw++] = PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0); |
| cs->buf[cs->cdw++] = STRMOUT_SELECT_BUFFER(i) | |
| STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_FROM_PACKET); /* control */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| cs->buf[cs->cdw++] = t[i]->b.buffer_offset >> 2; /* buffer offset in DW */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| } |
| } |
| #endif |
| } |
| } |
| |
| void si_context_streamout_end(struct r600_context *ctx) |
| { |
| struct radeon_winsys_cs *cs = ctx->cs; |
| struct si_so_target **t = ctx->so_targets; |
| unsigned i, flush_flags = 0; |
| |
| evergreen_flush_vgt_streamout(ctx); |
| |
| for (i = 0; i < ctx->num_so_targets; i++) { |
| #if 0 |
| if (t[i]) { |
| cs->buf[cs->cdw++] = PKT3(PKT3_STRMOUT_BUFFER_UPDATE, 4, 0); |
| cs->buf[cs->cdw++] = STRMOUT_SELECT_BUFFER(i) | |
| STRMOUT_OFFSET_SOURCE(STRMOUT_OFFSET_NONE) | |
| STRMOUT_STORE_BUFFER_FILLED_SIZE; /* control */ |
| cs->buf[cs->cdw++] = 0; /* dst address lo */ |
| cs->buf[cs->cdw++] = 0; /* dst address hi */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| cs->buf[cs->cdw++] = 0; /* unused */ |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0); |
| cs->buf[cs->cdw++] = |
| si_context_bo_reloc(ctx, t[i]->filled_size, |
| RADEON_USAGE_WRITE); |
| |
| flush_flags |= S_0085F0_SO0_DEST_BASE_ENA(1) << i; |
| } |
| #endif |
| } |
| |
| evergreen_set_streamout_enable(ctx, 0); |
| |
| ctx->atom_surface_sync.flush_flags |= flush_flags; |
| si_atom_dirty(ctx, &ctx->atom_surface_sync.atom); |
| |
| ctx->num_cs_dw_streamout_end = 0; |
| |
| /* XXX print some debug info */ |
| for (i = 0; i < ctx->num_so_targets; i++) { |
| if (!t[i]) |
| continue; |
| |
| uint32_t *ptr = ctx->ws->buffer_map(t[i]->filled_size->cs_buf, ctx->cs, RADEON_USAGE_READ); |
| printf("FILLED_SIZE%i: %u\n", i, *ptr); |
| ctx->ws->buffer_unmap(t[i]->filled_size->cs_buf); |
| } |
| } |
| |
| void evergreen_flush_vgt_streamout(struct si_context *ctx) |
| { |
| struct radeon_winsys_cs *cs = ctx->cs; |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONFIG_REG, 1, 0); |
| cs->buf[cs->cdw++] = (R_0084FC_CP_STRMOUT_CNTL - SI_CONFIG_REG_OFFSET) >> 2; |
| cs->buf[cs->cdw++] = 0; |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 0, 0); |
| cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_SO_VGTSTREAMOUT_FLUSH) | EVENT_INDEX(0); |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_WAIT_REG_MEM, 5, 0); |
| cs->buf[cs->cdw++] = WAIT_REG_MEM_EQUAL; /* wait until the register is equal to the reference value */ |
| cs->buf[cs->cdw++] = R_0084FC_CP_STRMOUT_CNTL >> 2; /* register */ |
| cs->buf[cs->cdw++] = 0; |
| cs->buf[cs->cdw++] = S_0084FC_OFFSET_UPDATE_DONE(1); /* reference value */ |
| cs->buf[cs->cdw++] = S_0084FC_OFFSET_UPDATE_DONE(1); /* mask */ |
| cs->buf[cs->cdw++] = 4; /* poll interval */ |
| } |
| |
| void evergreen_set_streamout_enable(struct si_context *ctx, unsigned buffer_enable_bit) |
| { |
| struct radeon_winsys_cs *cs = ctx->cs; |
| |
| if (buffer_enable_bit) { |
| cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 1, 0); |
| cs->buf[cs->cdw++] = (R_028B94_VGT_STRMOUT_CONFIG - SI_CONTEXT_REG_OFFSET) >> 2; |
| cs->buf[cs->cdw++] = S_028B94_STREAMOUT_0_EN(1); |
| |
| cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 1, 0); |
| cs->buf[cs->cdw++] = (R_028B98_VGT_STRMOUT_BUFFER_CONFIG - SI_CONTEXT_REG_OFFSET) >> 2; |
| cs->buf[cs->cdw++] = S_028B98_STREAM_0_BUFFER_EN(buffer_enable_bit); |
| } else { |
| cs->buf[cs->cdw++] = PKT3(PKT3_SET_CONTEXT_REG, 1, 0); |
| cs->buf[cs->cdw++] = (R_028B94_VGT_STRMOUT_CONFIG - SI_CONTEXT_REG_OFFSET) >> 2; |
| cs->buf[cs->cdw++] = S_028B94_STREAMOUT_0_EN(0); |
| } |
| } |
| |
| #endif |
| |
| struct pipe_stream_output_target * |
| si_create_so_target(struct pipe_context *ctx, |
| struct pipe_resource *buffer, |
| unsigned buffer_offset, |
| unsigned buffer_size) |
| { |
| #if 0 |
| struct si_context *rctx = (struct r600_context *)ctx; |
| struct si_so_target *t; |
| void *ptr; |
| |
| t = CALLOC_STRUCT(si_so_target); |
| if (!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; |
| |
| t->filled_size = si_resource_create_custom(ctx->screen, PIPE_USAGE_STATIC, 4); |
| ptr = rctx->ws->buffer_map(t->filled_size->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE); |
| memset(ptr, 0, t->filled_size->buf->size); |
| rctx->ws->buffer_unmap(t->filled_size->cs_buf); |
| |
| return &t->b; |
| #endif |
| return NULL; |
| } |
| |
| void si_so_target_destroy(struct pipe_context *ctx, |
| struct pipe_stream_output_target *target) |
| { |
| #if 0 |
| struct si_so_target *t = (struct r600_so_target*)target; |
| pipe_resource_reference(&t->b.buffer, NULL); |
| si_resource_reference(&t->filled_size, NULL); |
| FREE(t); |
| #endif |
| } |
| |
| void si_set_so_targets(struct pipe_context *ctx, |
| unsigned num_targets, |
| struct pipe_stream_output_target **targets, |
| unsigned append_bitmask) |
| { |
| assert(num_targets == 0); |
| #if 0 |
| struct si_context *rctx = (struct r600_context *)ctx; |
| unsigned i; |
| |
| /* Stop streamout. */ |
| if (rctx->num_so_targets) { |
| si_context_streamout_end(rctx); |
| } |
| |
| /* Set the new targets. */ |
| for (i = 0; i < num_targets; i++) { |
| pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->so_targets[i], targets[i]); |
| } |
| for (; i < rctx->num_so_targets; i++) { |
| pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->so_targets[i], NULL); |
| } |
| |
| rctx->num_so_targets = num_targets; |
| rctx->streamout_start = num_targets != 0; |
| rctx->streamout_append_bitmask = append_bitmask; |
| #endif |
| } |