v2: Set CB_TARGET_MASK to zero for compute resources (Marek). Remove unnecessary use of util_range_add (Marek). Fix crash on non-contiguous RAT setup. v3: Unreference surface instead of calling destroy directly (Marek).
Non-contiguous RAT setup can occur when the kernel signature contains no global buffer arguments, but there are write-only image args. In this case RAT0 is not set, but RAT1 is. --- src/gallium/drivers/r600/evergreen_compute.c | 106 +++++++++++++++++---------- src/gallium/drivers/r600/evergreen_state.c | 43 ++++++++++- src/gallium/drivers/r600/r600_pipe.h | 4 +- src/gallium/drivers/radeon/r600_texture.c | 1 + 4 files changed, 113 insertions(+), 41 deletions(-) diff --git a/src/gallium/drivers/r600/evergreen_compute.c b/src/gallium/drivers/r600/evergreen_compute.c index b191e0d..e98e3d8 100644 --- a/src/gallium/drivers/r600/evergreen_compute.c +++ b/src/gallium/drivers/r600/evergreen_compute.c @@ -99,8 +99,40 @@ struct r600_resource* r600_compute_buffer_alloc_vram( return (struct r600_resource *)buffer; } +static void evergreen_set_cbuf( + struct r600_context *ctx, + unsigned id, + struct pipe_surface *surf) +{ + struct pipe_framebuffer_state *state = &ctx->framebuffer.state; + + /* Add the RAT to the list of color buffers */ + state->cbufs[id] = surf; + + /* Update the number of color buffers */ + state->nr_cbufs = MAX2(id + 1, state->nr_cbufs); + + /* cb_target_mask should be 0 for compute resources. */ + ctx->compute_cb_target_mask &= ~(0xf << (id << 2)); +} -static void evergreen_set_rat( +static void evergreen_unset_cbuf( + struct r600_context *ctx, + unsigned id) +{ + unsigned i; + struct pipe_framebuffer_state *state = &ctx->framebuffer.state; + + state->cbufs[id] = NULL; + for (i = state->nr_cbufs; i > 0; --i) { + if (state->cbufs[i - 1]) { + break; + } + } + state->nr_cbufs = i; +} + +static void evergreen_set_rat_buf( struct r600_context *ctx, unsigned id, struct r600_resource* bo, @@ -123,23 +155,11 @@ static void evergreen_set_rat( rat_templ.u.tex.first_layer = 0; rat_templ.u.tex.last_layer = 0; - /* Add the RAT the list of color buffers */ - ctx->framebuffer.state.cbufs[id] = ctx->b.b.create_surface( - (struct pipe_context *)ctx, - (struct pipe_resource *)bo, &rat_templ); - - /* Update the number of color buffers */ - ctx->framebuffer.state.nr_cbufs = - MAX2(id + 1, ctx->framebuffer.state.nr_cbufs); - - /* Update the cb_target_mask - * XXX: I think this is a potential spot for bugs once we start doing - * GL interop. cb_target_mask may be modified in the 3D sections - * of this driver. */ - ctx->compute_cb_target_mask |= (0xf << (id * 4)); + evergreen_set_cbuf(ctx, id, ctx->b.b.create_surface( + (struct pipe_context *)ctx, (struct pipe_resource *)bo, &rat_templ)); surf = (struct r600_surface*)ctx->framebuffer.state.cbufs[id]; - evergreen_init_color_surface_rat(rctx, surf); + evergreen_init_color_surface_rat_buf(ctx, surf); } static void evergreen_cs_set_vertex_buffer( @@ -436,6 +456,8 @@ static void compute_emit_cs(struct r600_context *ctx, const uint *block_layout, /* XXX support more than 8 colorbuffers (the offsets are not a multiple of 0x3C for CB8-11) */ for (i = 0; i < 8 && i < ctx->framebuffer.state.nr_cbufs; i++) { struct r600_surface *cb = (struct r600_surface*)ctx->framebuffer.state.cbufs[i]; + if (!cb) + continue; unsigned reloc = r600_context_bo_reloc(&ctx->b, &ctx->b.rings.gfx, (struct r600_resource*)cb->base.texture, RADEON_USAGE_READWRITE, @@ -623,32 +645,34 @@ static void evergreen_set_compute_resources(struct pipe_context * ctx_, struct pipe_surface ** surfaces) { struct r600_context *ctx = (struct r600_context *)ctx_; - struct r600_surface **resources = (struct r600_surface **)surfaces; + struct pipe_surface *surf = NULL; COMPUTE_DBG(ctx->screen, "*** evergreen_set_compute_resources: start = %u count = %u\n", start, count); + if (!surfaces) { + for (unsigned i = 0; i < count; ++i) + evergreen_unset_cbuf(ctx, 1 + i); + return; + } + for (unsigned i = 0; i < count; i++) { - /* The First two vertex buffers are reserved for parameters and - * global buffers. */ - unsigned vtx_id = 2 + i; - if (resources[i]) { - struct r600_resource_global *buffer = - (struct r600_resource_global*) - resources[i]->base.texture; - if (resources[i]->base.writable) { - assert(i+1 < 12); - - evergreen_set_rat(ctx->cs_shader_state.shader, i+1, - (struct r600_resource *)resources[i]->base.texture, - buffer->chunk->start_in_dw*4, - resources[i]->base.texture->width0); - } - - evergreen_cs_set_vertex_buffer(ctx, vtx_id, - buffer->chunk->start_in_dw * 4, - resources[i]->base.texture); - } + surf = surfaces[i]; + if (!surf) + continue; + + /* XXX: Implement constant buffers. */ + assert(surf->writable && + "Constant buffer compute resources are not supported yet."); + + /* It is assumed, that surface[i]->texture contains an r600_texture. */ + + /* The first RAT is reserved for global buffers. */ + unsigned rat_id = 1 + i; + assert(rat_id < 12); + + evergreen_set_cbuf(ctx, rat_id, surf); + evergreen_init_color_surface_rat_tex(ctx, (struct r600_surface *)surf); } } @@ -686,7 +710,11 @@ static void evergreen_set_global_binding( first, n); if (!resources) { - /* XXX: Unset */ + if (n) { + /* evergreen_set_rat_buf creates a new surface. */ + pipe_surface_reference(&ctx->framebuffer.state.cbufs[0], NULL); + evergreen_unset_cbuf(ctx, 0); + } return; } @@ -717,7 +745,7 @@ static void evergreen_set_global_binding( *(handles[i]) = util_cpu_to_le32(handle); } - evergreen_set_rat(ctx, 0, pool->bo, 0, pool->size_in_dw * 4); + evergreen_set_rat_buf(ctx, 0, pool->bo, 0, pool->size_in_dw * 4); evergreen_cs_set_vertex_buffer(ctx, 1, 0, (struct pipe_resource*)pool->bo); } diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index a21cd3d..142896d 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -45,6 +45,31 @@ static inline unsigned evergreen_array_mode(unsigned mode) } } +static inline unsigned evergreen_resource_type(enum pipe_texture_target target) +{ + switch (target) { + case PIPE_BUFFER: + return V_028C70_BUFFER; + case PIPE_TEXTURE_1D: + return V_028C70_TEXTURE1D; + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D: + return V_028C70_TEXTURE2D; + case PIPE_TEXTURE_3D: + return V_028C70_TEXTURE3D; + case PIPE_TEXTURE_1D_ARRAY: + return V_028C70_TEXTURE1DARRAY; + case PIPE_TEXTURE_2D_ARRAY: + return V_028C70_TEXTURE2DARRAY; + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_CUBE_ARRAY: + assert(0 && "Can't assign CB_COLOR_INFO resource type to " + "PIPE_TEXTURE_CUBE or PIPE_TEXTURE_CUBE_ARRAY."); + default: + assert(0 && "Unknown pipe texture target."); + } +} + static uint32_t eg_num_banks(uint32_t nbanks) { switch (nbanks) { @@ -923,7 +948,7 @@ static void evergreen_emit_scissor_state(struct r600_context *rctx, struct r600_ * to be used for 1D aligned buffers that do not have an associated * radeon_surf. */ -void evergreen_init_color_surface_rat(struct r600_context *rctx, +void evergreen_init_color_surface_rat_buf(struct r600_context *rctx, struct r600_surface *surf) { struct pipe_resource *pipe_buffer = surf->base.texture; @@ -961,6 +986,7 @@ void evergreen_init_color_surface_rat(struct r600_context *rctx, | S_028C70_BLEND_BYPASS(1) /* We must set this bit because we * are using NUMBER_UINT */ | S_028C70_RAT(1) + | S_028C70_RESOURCE_TYPE(V_028C70_BUFFER) ; surf->cb_color_attrib = S_028C74_NON_DISP_TILING_ORDER(1); @@ -977,6 +1003,18 @@ void evergreen_init_color_surface_rat(struct r600_context *rctx, surf->cb_color_fmask_slice = 0; } +void evergreen_init_color_surface_rat_tex(struct r600_context *rctx, + struct r600_surface *surf) +{ + struct r600_texture *tex = (struct r600_texture *)surf->base.texture; + + evergreen_init_color_surface(rctx, surf); + + surf->cb_color_info |= S_028C70_RAT(1) | + S_028C70_RESOURCE_TYPE(evergreen_resource_type( + tex->resource.b.b.target)); +} + void evergreen_init_color_surface(struct r600_context *rctx, struct r600_surface *surf) { @@ -1145,6 +1183,9 @@ void evergreen_init_color_surface(struct r600_context *rctx, base_offset = rtex->resource.gpu_address; + color_dim = S_028C78_WIDTH_MAX(rtex->resource.b.b.width0 - 1) | + S_028C78_HEIGHT_MAX(rtex->resource.b.b.height0 - 1); + /* XXX handle enabling of CB beyond BASE8 which has different offset */ surf->cb_color_base = (base_offset + offset) >> 8; surf->cb_color_dim = color_dim; diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 5d10bb4..4431f93 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -627,7 +627,9 @@ boolean evergreen_is_format_supported(struct pipe_screen *screen, unsigned usage); void evergreen_init_color_surface(struct r600_context *rctx, struct r600_surface *surf); -void evergreen_init_color_surface_rat(struct r600_context *rctx, +void evergreen_init_color_surface_rat_buf(struct r600_context *rctx, + struct r600_surface *surf); +void evergreen_init_color_surface_rat_tex(struct r600_context *rctx, struct r600_surface *surf); void evergreen_update_db_shader_control(struct r600_context * rctx); diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index 57c40d9..0eaab34 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -1116,6 +1116,7 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe, surface->base.width = width; surface->base.height = height; surface->base.u = templ->u; + surface->base.writable = templ->writable; return &surface->base; } -- 2.4.6 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev