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

Reply via email to