From 059c096eff1a380fe72be675893a401d6c7dfa1a Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 29 Jun 2018 12:58:31 -0700 Subject: iris: SO buffers --- src/gallium/drivers/iris/iris_state.c | 101 ++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 11 deletions(-) (limited to 'src/gallium/drivers/iris/iris_state.c') diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 5db1319984f..9d1f3d9dcf5 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -276,6 +276,13 @@ ro_bo(struct iris_bo *bo, uint64_t offset) return (struct iris_address) { .bo = bo, .offset = offset }; } +static struct iris_address +rw_bo(struct iris_bo *bo, uint64_t offset) +{ + /* Not for CSOs! */ + return (struct iris_address) { .bo = bo, .offset = offset, .write = true }; +} + static void * upload_state(struct u_upload_mgr *uploader, struct iris_state_ref *ref, @@ -424,6 +431,8 @@ struct iris_genx_state { struct iris_viewport_state viewport; struct iris_vertex_buffer_state vertex_buffers; struct iris_depth_buffer_state depth_buffer; + + uint32_t so_buffers[4 * GENX(3DSTATE_SO_BUFFER_length)]; }; static void @@ -764,6 +773,9 @@ iris_bind_rasterizer_state(struct pipe_context *ctx, void *state) if (cso_changed(line_stipple_enable) || cso_changed(poly_stipple_enable)) ice->state.dirty |= IRIS_DIRTY_WM; + + if (cso_changed(rasterizer_discard)) + ice->state.dirty |= IRIS_DIRTY_STREAMOUT; } ice->state.cso_rast = new_cso; @@ -1621,30 +1633,60 @@ iris_create_compute_state(struct pipe_context *ctx, return malloc(1); } +struct iris_stream_output_target { + struct pipe_stream_output_target base; + + uint32_t so_buffer[GENX(3DSTATE_SO_BUFFER_length)]; + + struct iris_state_ref offset; +}; + static struct pipe_stream_output_target * iris_create_stream_output_target(struct pipe_context *ctx, struct pipe_resource *res, unsigned buffer_offset, unsigned buffer_size) { - struct pipe_stream_output_target *t = - CALLOC_STRUCT(pipe_stream_output_target); - if (!t) + struct iris_stream_output_target *cso = calloc(1, sizeof(*cso)); + if (!cso) return NULL; - pipe_reference_init(&t->reference, 1); - pipe_resource_reference(&t->buffer, res); - t->buffer_offset = buffer_offset; - t->buffer_size = buffer_size; - return t; + pipe_reference_init(&cso->base.reference, 1); + pipe_resource_reference(&cso->base.buffer, res); + cso->base.buffer_offset = buffer_offset; + cso->base.buffer_size = buffer_size; + cso->base.context = ctx; + + upload_state(ctx->stream_uploader, &cso->offset, 4, 4); + + iris_pack_command(GENX(3DSTATE_SO_BUFFER), cso->so_buffer, sob) { + sob.SurfaceBaseAddress = + rw_bo(NULL, iris_resource_bo(res)->gtt_offset + buffer_offset); + sob.SOBufferEnable = true; + sob.StreamOffsetWriteEnable = true; + sob.StreamOutputBufferOffsetAddressEnable = true; + sob.MOCS = MOCS_WB; // XXX: MOCS + + sob.SurfaceSize = MAX2(buffer_size / 4, 1) - 1; + sob.StreamOutputBufferOffsetAddress = + rw_bo(NULL, iris_resource_bo(cso->offset.res)->gtt_offset + cso->offset.offset); + + /* .SOBufferIndex and .StreamOffset are filled in later */ + } + + return &cso->base; } static void iris_stream_output_target_destroy(struct pipe_context *ctx, - struct pipe_stream_output_target *t) + struct pipe_stream_output_target *state) { - pipe_resource_reference(&t->buffer, NULL); - free(t); + struct iris_stream_output_target *cso = (void *) state; + + pipe_resource_reference(&cso->base.buffer, NULL); + pipe_resource_reference(&cso->offset.res, NULL); + + free(cso); } static void @@ -1653,6 +1695,37 @@ iris_set_stream_output_targets(struct pipe_context *ctx, struct pipe_stream_output_target **targets, const unsigned *offsets) { + struct iris_context *ice = (struct iris_context *) ctx; + uint32_t *so_buffers = ice->state.genx->so_buffers; + + for (unsigned i = 0; i < 4; i++, + so_buffers += GENX(3DSTATE_SO_BUFFER_length)) { + + if (i >= num_targets || !targets[i]) { + iris_pack_command(GENX(3DSTATE_SO_BUFFER), so_buffers, sob) + sob.SOBufferIndex = i; + continue; + } + + /* Note that offsets[i] will either be 0, causing us to zero + * the value in the buffer, or 0xFFFFFFFF, which happens to mean + * "continue appending at the existing offset." + */ + assert(offsets[i] == 0 || offsets[i] == 0xFFFFFFFF); + + uint32_t dynamic[GENX(3DSTATE_SO_BUFFER_length)]; + iris_pack_state(GENX(3DSTATE_SO_BUFFER), dynamic, dyns) { + dyns.SOBufferIndex = i; + dyns.StreamOffset = offsets[i]; + } + + struct iris_stream_output_target *tgt = (void *) targets[i]; + for (uint32_t j = 0; j < GENX(3DSTATE_SO_BUFFER_length); j++) { + so_buffers[j] = tgt->so_buffer[j] | dynamic[j]; + } + } + + ice->state.dirty |= IRIS_DIRTY_SO_BUFFERS; } static uint32_t * @@ -2579,6 +2652,7 @@ iris_upload_render_state(struct iris_context *ice, { const uint64_t dirty = ice->state.dirty; + struct iris_genx_state *genx = ice->state.genx; struct brw_wm_prog_data *wm_prog_data = (void *) ice->shaders.prog[MESA_SHADER_FRAGMENT]->prog_data; @@ -2783,6 +2857,11 @@ iris_upload_render_state(struct iris_context *ice, } } + if (dirty & IRIS_DIRTY_SO_BUFFERS) { + iris_batch_emit(batch, genx->so_buffers, + 4 * 4 * GENX(3DSTATE_SO_BUFFER_length)); + } + if ((dirty & IRIS_DIRTY_SO_DECL_LIST) && ice->state.so_decl_list) { iris_batch_emit(batch, ice->state.so_decl_list, 4 * ((ice->state.so_decl_list[0] & 0xff) + 2)); -- cgit v1.2.3