r600g: partialy fix texturing from depth buffer + initial support for untiling
authorJerome Glisse <jglisse@redhat.com>
Sun, 22 Aug 2010 02:49:22 +0000 (22:49 -0400)
committerJerome Glisse <jglisse@redhat.com>
Sun, 22 Aug 2010 02:52:38 +0000 (22:52 -0400)
Partialy fix texturing from depth buffer, depth buffer is tiled
following different tile organisation that color buffer. This
properly set the tile type & array mode field of texture sampler
when sampling from db resource.

Add initial support to untiling buffer when transfering them,
it's kind of broken by corruption the vertex buffer of previous
draw.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_context.c
src/gallium/drivers/r600/r600_resource.h
src/gallium/drivers/r600/r600_screen.h
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_texture.c

index aef4fbd9af93a22a90b681bd8230b52dd17bf04d..dc57b333a03860477b44952a2a1df8d04f3a0f48 100644 (file)
@@ -120,7 +120,8 @@ static void r600_clear_depth_stencil(struct pipe_context *ctx,
        r600_queries_resume(ctx);
 }
 
-static void r600_resource_copy_region(struct pipe_context *pipe,
+
+static void r600_resource_copy_region(struct pipe_context *ctx,
                                      struct pipe_resource *dst,
                                      struct pipe_subresource subdst,
                                      unsigned dstx, unsigned dsty, unsigned dstz,
@@ -129,8 +130,28 @@ static void r600_resource_copy_region(struct pipe_context *pipe,
                                      unsigned srcx, unsigned srcy, unsigned srcz,
                                      unsigned width, unsigned height)
 {
-       util_resource_copy_region(pipe, dst, subdst, dstx, dsty, dstz,
-                                 src, subsrc, srcx, srcy, srcz, width, height);
+       struct r600_context *rctx = r600_context(ctx);
+       struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
+       struct pipe_sampler_state *samplers[PIPE_MAX_ATTRIBS];
+       struct pipe_sampler_view_state *sampler_views[PIPE_MAX_ATTRIBS];
+       unsigned i;
+
+       for (i = 0; i < rctx->ps_nsampler_view; i++) {
+               sampler_views[i] = &rctx->ps_sampler_view[i]->state.sampler_view;
+       }
+       for (i = 0; i < rctx->ps_nsampler; i++) {
+               samplers[i] = &rctx->ps_sampler[i]->state.sampler;
+       }
+       r600_blitter_save_states(ctx);
+       util_blitter_save_framebuffer(rctx->blitter, fb);
+       util_blitter_save_fragment_sampler_states(rctx->blitter, rctx->ps_nsampler, samplers);
+       util_blitter_save_fragment_sampler_views(rctx->blitter, rctx->ps_nsampler_view, sampler_views);
+
+       util_blitter_copy_region(rctx->blitter, dst, subdst, dstx, dsty, dstz,
+                       src, subsrc, srcx, srcy, srcz, width, height,
+                       TRUE);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
 void r600_init_blit_functions(struct r600_context *rctx)
index 2f59a550f5655377acaa3a10002b75745a902ff1..9af28356c5c9081516e5688d5cc0d95eff596725 100644 (file)
@@ -52,7 +52,7 @@ void r600_flush(struct pipe_context *ctx, unsigned flags,
        char dname[256];
 
        /* suspend queries */
-       r600_queries_suspend(rctx);
+       r600_queries_suspend(ctx);
        if (radeon_ctx_pm4(rctx->ctx))
                goto out;
        /* FIXME dumping should be removed once shader support instructions
@@ -61,8 +61,10 @@ void r600_flush(struct pipe_context *ctx, unsigned flags,
        if (!rctx->ctx->cpm4)
                goto out;
        sprintf(dname, "gallium-%08d.bof", dc);
-       if (dc < 10)
+       if (dc < 2) {
                radeon_ctx_dump_bof(rctx->ctx, dname);
+               R600_ERR("dumped %s\n", dname);
+       }
 #if 1
        radeon_ctx_submit(rctx->ctx);
 #endif
@@ -74,7 +76,7 @@ out:
        rctx->ctx = radeon_ctx_decref(rctx->ctx);
        rctx->ctx = radeon_ctx(rscreen->rw);
        /* resume queries */
-       r600_queries_resume(rctx);
+       r600_queries_resume(ctx);
 }
 
 static void r600_init_config(struct r600_context *rctx)
index bb90e76fb78dae66677d8925f58ea7f46f1a9e54..5ebda027e914e6d7d892ea1a6aa069a5cbacb825 100644 (file)
@@ -48,6 +48,9 @@ struct r600_resource_texture {
        unsigned long                   pitch_override;
        unsigned long                   bpt;
        unsigned long                   size;
+       unsigned                        tilled;
+       unsigned                        array_mode;
+       unsigned                        tile_type;
 };
 
 void r600_init_context_resource_functions(struct r600_context *r600);
index 53b560c617f000f1bf5e05dee7e6dedc92964ed2..147be3c4ac0cf554adac824de4ec7b5dcfc6e0bc 100644 (file)
@@ -38,6 +38,7 @@ struct r600_transfer {
        /* Buffer transfer. */
        struct pipe_transfer            *buffer_transfer;
        unsigned                        offset;
+       struct pipe_resource            *linear_texture;
 };
 
 struct r600_screen {
index da1af6702c3d6876be3211045cea9d4b02dbcc66..79fc04a9fe321f71c84df8ec7ad577dd524bca6c 100644 (file)
@@ -105,8 +105,8 @@ int r600_pipe_shader_create(struct pipe_context *ctx,
        struct r600_screen *rscreen = r600_screen(ctx->screen);
        int r;
 
-fprintf(stderr, "--------------------------------------------------------------\n");
-tgsi_dump(tokens, 0);
+//fprintf(stderr, "--------------------------------------------------------------\n");
+//tgsi_dump(tokens, 0);
        if (rpshader == NULL)
                return -ENOMEM;
        rpshader->shader.family = radeon_get_family(rscreen->rw);
@@ -120,7 +120,7 @@ tgsi_dump(tokens, 0);
                R600_ERR("building bytecode failed !\n");
                return r;
        }
-fprintf(stderr, "______________________________________________________________\n");
+//fprintf(stderr, "______________________________________________________________\n");
        return 0;
 }
 
index 93fc68e42ef0234a7927b9cd123b2817f165ecd8..e9b03f571add168a531a520ff0987799e3b62262 100644 (file)
@@ -773,6 +773,9 @@ static struct radeon_state *r600_db(struct r600_context *rctx)
                return NULL;
 
        rtex = (struct r600_resource_texture*)state->zsbuf->texture;
+       rtex->tilled = 1;
+       rtex->array_mode = 2;
+       rtex->tile_type = 1;
        rbuffer = &rtex->resource;
        rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
        rstate->nbo = 1;
@@ -1258,7 +1261,9 @@ static struct radeon_state *r600_resource(struct r600_context *rctx,
        /* FIXME properly handle first level != 0 */
        rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD0] =
                        S_038000_DIM(r600_tex_dim(view->texture->target)) |
-                       S_038000_PITCH((pitch / 8) - 1) |
+                       S_038000_TILE_MODE(tmp->array_mode) |
+                       S_038000_TILE_TYPE(tmp->tile_type) |
+                       S_038000_PITCH((pitch / 8) - 1) |
                        S_038000_TEX_WIDTH(view->texture->width0 - 1);
        rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD1] =
                        S_038004_TEX_HEIGHT(view->texture->height0 - 1) |
index 8a6b5f87648533fab362598bbf1ee251049b94a0..92b4f430c57ef0465d6ccaaa68469354d3c724eb 100644 (file)
 
 extern struct u_resource_vtbl r600_texture_vtbl;
 
+/* Copy from a tiled texture to a detiled one. */
+static void r600_copy_from_tiled_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
+{
+       struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
+       struct pipe_resource *texture = transfer->resource;
+       struct pipe_subresource subdst;
+
+       subdst.face = 0;
+       subdst.level = 0;
+       ctx->resource_copy_region(ctx, rtransfer->linear_texture,
+                               subdst, 0, 0, 0, texture, transfer->sr,
+                               transfer->box.x, transfer->box.y, transfer->box.z,
+                               transfer->box.width, transfer->box.height);
+}
+
 static unsigned long r600_texture_get_offset(struct r600_resource_texture *rtex,
                                        unsigned level, unsigned zslice,
                                        unsigned face)
@@ -106,7 +121,6 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
                FREE(rtex);
                return NULL;
        }
-
        return &resource->base.b;
 }
 
@@ -208,6 +222,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                                                const struct pipe_box *box)
 {
        struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
+       struct pipe_resource resource;
        struct r600_transfer *trans;
 
        trans = CALLOC_STRUCT(r600_transfer);
@@ -219,14 +234,56 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
        trans->transfer.box = *box;
        trans->transfer.stride = rtex->pitch[sr.level];
        trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
+       if (rtex->tilled) {
+               resource.target = PIPE_TEXTURE_2D;
+               resource.format = texture->format;
+               resource.width0 = box->width;
+               resource.height0 = box->height;
+               resource.depth0 = 0;
+               resource.last_level = 0;
+               resource.nr_samples = 0;
+               resource.usage = PIPE_USAGE_DYNAMIC;
+               resource.bind = 0;
+               resource.flags = 0;
+               /* For texture reading, the temporary (detiled) texture is used as
+                * a render target when blitting from a tiled texture. */
+               if (usage & PIPE_TRANSFER_READ) {
+                       resource.bind |= PIPE_BIND_RENDER_TARGET;
+               }
+               /* For texture writing, the temporary texture is used as a sampler
+                * when blitting into a tiled texture. */
+               if (usage & PIPE_TRANSFER_WRITE) {
+                       resource.bind |= PIPE_BIND_SAMPLER_VIEW;
+               }
+               /* Create the temporary texture. */
+               trans->linear_texture = ctx->screen->resource_create(ctx->screen, &resource);
+               if (trans->linear_texture == NULL) {
+                       R600_ERR("failed to create temporary texture to hold untiled copy\n");
+                       pipe_resource_reference(&trans->transfer.resource, NULL);
+                       FREE(trans);
+                       return NULL;
+               }
+               if (usage & PIPE_TRANSFER_READ) {
+                       /* We cannot map a tiled texture directly because the data is
+                        * in a different order, therefore we do detiling using a blit. */
+                       r600_copy_from_tiled_texture(ctx, trans);
+                       /* Always referenced in the blit. */
+                       ctx->flush(ctx, 0, NULL);
+               }
+       }
        return &trans->transfer;
 }
 
 void r600_texture_transfer_destroy(struct pipe_context *ctx,
-                                  struct pipe_transfer *trans)
+                                  struct pipe_transfer *transfer)
 {
-       pipe_resource_reference(&trans->resource, NULL);
-       FREE(trans);
+       struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
+
+       if (rtransfer->linear_texture) {
+               pipe_resource_reference(&rtransfer->linear_texture, NULL);
+       }
+       pipe_resource_reference(&transfer->resource, NULL);
+       FREE(transfer);
 }
 
 void* r600_texture_transfer_map(struct pipe_context *ctx,
@@ -239,14 +296,20 @@ void* r600_texture_transfer_map(struct pipe_context *ctx,
        char *map;
 
        r600_flush(ctx, 0, NULL);
-
-       resource = (struct r600_resource *)transfer->resource;
+       if (rtransfer->linear_texture) {
+               resource = (struct r600_resource *)rtransfer->linear_texture;
+       } else {
+               resource = (struct r600_resource *)transfer->resource;
+       }
        if (radeon_bo_map(rscreen->rw, resource->bo)) {
                return NULL;
        }
        radeon_bo_wait(rscreen->rw, resource->bo);
 
        map = resource->bo->data;
+       if (rtransfer->linear_texture) {
+               return map;
+       }
 
        return map + rtransfer->offset +
                transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
@@ -256,10 +319,15 @@ void* r600_texture_transfer_map(struct pipe_context *ctx,
 void r600_texture_transfer_unmap(struct pipe_context *ctx,
                                 struct pipe_transfer* transfer)
 {
+       struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
        struct r600_screen *rscreen = r600_screen(ctx->screen);
        struct r600_resource *resource;
 
-       resource = (struct r600_resource *)transfer->resource;
+       if (rtransfer->linear_texture) {
+               resource = (struct r600_resource *)rtransfer->linear_texture;
+       } else {
+               resource = (struct r600_resource *)transfer->resource;
+       }
        radeon_bo_unmap(rscreen->rw, resource->bo);
 }
 
@@ -283,51 +351,51 @@ void r600_init_screen_texture_functions(struct pipe_screen *screen)
 }
 
 static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
-                                         const unsigned char *swizzle_view)
+               const unsigned char *swizzle_view)
 {
-    unsigned i;
-    unsigned char swizzle[4];
-    unsigned result = 0;
-    const uint32_t swizzle_shift[4] = {
-           16, 19, 22, 25,
-    };
-    const uint32_t swizzle_bit[4] = {
-           0, 1, 2, 3,
-    };
-
-    if (swizzle_view) {
-        /* Combine two sets of swizzles. */
-        for (i = 0; i < 4; i++) {
-            swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
-                         swizzle_format[swizzle_view[i]] : swizzle_view[i];
-        }
-    } else {
-        memcpy(swizzle, swizzle_format, 4);
-    }
-
-    /* Get swizzle. */
-    for (i = 0; i < 4; i++) {
-        switch (swizzle[i]) {
-            case UTIL_FORMAT_SWIZZLE_Y:
-                result |= swizzle_bit[1] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_Z:
-                result |= swizzle_bit[2] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_W:
-                result |= swizzle_bit[3] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_0:
-                result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_1:
-                result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
-                break;
-            default: /* UTIL_FORMAT_SWIZZLE_X */
-                result |= swizzle_bit[0] << swizzle_shift[i];
-        }
-    }
-    return result;
+       unsigned i;
+       unsigned char swizzle[4];
+       unsigned result = 0;
+       const uint32_t swizzle_shift[4] = {
+               16, 19, 22, 25,
+       };
+       const uint32_t swizzle_bit[4] = {
+               0, 1, 2, 3,
+       };
+
+       if (swizzle_view) {
+               /* Combine two sets of swizzles. */
+               for (i = 0; i < 4; i++) {
+                       swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
+                               swizzle_format[swizzle_view[i]] : swizzle_view[i];
+               }
+       } else {
+               memcpy(swizzle, swizzle_format, 4);
+       }
+
+       /* Get swizzle. */
+       for (i = 0; i < 4; i++) {
+               switch (swizzle[i]) {
+               case UTIL_FORMAT_SWIZZLE_Y:
+                       result |= swizzle_bit[1] << swizzle_shift[i];
+                       break;
+               case UTIL_FORMAT_SWIZZLE_Z:
+                       result |= swizzle_bit[2] << swizzle_shift[i];
+                       break;
+               case UTIL_FORMAT_SWIZZLE_W:
+                       result |= swizzle_bit[3] << swizzle_shift[i];
+                       break;
+               case UTIL_FORMAT_SWIZZLE_0:
+                       result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
+                       break;
+               case UTIL_FORMAT_SWIZZLE_1:
+                       result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
+                       break;
+               default: /* UTIL_FORMAT_SWIZZLE_X */
+                       result |= swizzle_bit[0] << swizzle_shift[i];
+               }
+       }
+       return result;
 }
 
 /* texture format translate */
@@ -353,13 +421,13 @@ uint32_t r600_translate_texformat(enum pipe_format format,
        case UTIL_FORMAT_COLORSPACE_ZS:
                switch (format) {
                case PIPE_FORMAT_Z16_UNORM:
-                       result = V_028010_DEPTH_16;
+                       result = V_0280A0_COLOR_16;
                        goto out_word4;
                case PIPE_FORMAT_Z24X8_UNORM:
-                       result = V_028010_DEPTH_X8_24;
+                       result = V_0280A0_COLOR_8_24;
                        goto out_word4;
                case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-                       result = V_028010_DEPTH_8_24;
+                       result = V_0280A0_COLOR_8_24;
                        goto out_word4;
                default:
                        goto out_unknown;
@@ -522,9 +590,8 @@ out_word4:
                *word4_p = word4;
        if (yuv_format_p)
                *yuv_format_p = yuv_format;
-//     fprintf(stderr,"returning %08x %08x %08x\n", result, word4, yuv_format);
        return result;
 out_unknown:
-//     R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
+       R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
        return ~0;
 }