[Mesa-dev] [PATCH 2/3] gallium: change pipe_image_view::first_element/last_element -> offset/size

Marek Olšák maraeo at gmail.com
Fri Aug 12 16:46:23 UTC 2016


From: Marek Olšák <marek.olsak at amd.com>

This is required by OpenGL. Our hardware supports this.

Example: Bind RGBA32F with offset = 4 bytes.
---
 src/gallium/auxiliary/util/u_dump_state.c     |  4 ++--
 src/gallium/drivers/nouveau/nvc0/nvc0_state.c |  4 ++--
 src/gallium/drivers/nouveau/nvc0/nvc0_tex.c   | 24 +++++++-----------------
 src/gallium/drivers/radeonsi/si_descriptors.c | 16 ++++------------
 src/gallium/drivers/softpipe/sp_image.c       |  6 +++---
 src/gallium/drivers/trace/tr_dump_state.c     |  4 ++--
 src/gallium/include/pipe/p_state.h            |  4 ++--
 src/mesa/state_tracker/st_atom_image.c        | 10 ++--------
 src/mesa/state_tracker/st_cb_readpixels.c     |  5 +++--
 9 files changed, 27 insertions(+), 50 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c
index 4568dc6..6aecee1 100644
--- a/src/gallium/auxiliary/util/u_dump_state.c
+++ b/src/gallium/auxiliary/util/u_dump_state.c
@@ -715,22 +715,22 @@ util_dump_image_view(FILE *stream, const struct pipe_image_view *state)
       util_dump_null(stream);
       return;
    }
 
    util_dump_struct_begin(stream, "pipe_image_view");
 
    util_dump_member(stream, ptr, state, resource);
    util_dump_member(stream, format, state, format);
 
    if (state->resource->target == PIPE_BUFFER) {
-      util_dump_member(stream, uint, state, u.buf.first_element);
-      util_dump_member(stream, uint, state, u.buf.last_element);
+      util_dump_member(stream, uint, state, u.buf.offset);
+      util_dump_member(stream, uint, state, u.buf.size);
    }
    else {
       util_dump_member(stream, uint, state, u.tex.first_layer);
       util_dump_member(stream, uint, state, u.tex.last_layer);
       util_dump_member(stream, uint, state, u.tex.level);
    }
 
    util_dump_struct_end(stream);
 }
 
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
index fcb695a..b9ac9f4 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
@@ -1264,22 +1264,22 @@ nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s,
       for (i = start; i < end; ++i) {
          struct pipe_image_view *img = &nvc0->images[s][i];
          const unsigned p = i - start;
 
          if (img->resource == pimages[p].resource &&
              img->format == pimages[p].format &&
              img->access == pimages[p].access) {
             if (img->resource == NULL)
                continue;
             if (img->resource->target == PIPE_BUFFER &&
-                img->u.buf.first_element == pimages[p].u.buf.first_element &&
-                img->u.buf.last_element == pimages[p].u.buf.last_element)
+                img->u.buf.offset == pimages[p].u.buf.offset &&
+                img->u.buf.size == pimages[p].u.buf.size)
                continue;
             if (img->resource->target != PIPE_BUFFER &&
                 img->u.tex.first_layer == pimages[p].u.tex.first_layer &&
                 img->u.tex.last_layer == pimages[p].u.tex.last_layer &&
                 img->u.tex.level == pimages[p].u.tex.level)
                continue;
          }
 
          mask |= (1 << i);
          if (pimages[p].resource)
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
index b6e0ba8..4fa2621 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
@@ -252,25 +252,22 @@ gm107_create_texture_view_from_image(struct pipe_context *pipe,
    if (target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY)
       target = PIPE_TEXTURE_2D_ARRAY;
 
    templ.format = view->format;
    templ.swizzle_r = PIPE_SWIZZLE_X;
    templ.swizzle_g = PIPE_SWIZZLE_Y;
    templ.swizzle_b = PIPE_SWIZZLE_Z;
    templ.swizzle_a = PIPE_SWIZZLE_W;
 
    if (target == PIPE_BUFFER) {
-      templ.u.buf.offset = view->u.buf.first_element *
-                           util_format_get_blocksize(view->format);
-      templ.u.buf.size = (view->u.buf.last_element -
-                          view->u.buf.first_element + 1) *
-                         util_format_get_blocksize(view->format);
+      templ.u.buf.offset = view->u.buf.offset;
+      templ.u.buf.size = view->u.buf.size;
    } else {
       templ.u.tex.first_layer = view->u.tex.first_layer;
       templ.u.tex.last_layer = view->u.tex.last_layer;
       templ.u.tex.first_level = templ.u.tex.last_level = view->u.tex.level;
    }
 
    flags = NV50_TEXVIEW_SCALED_COORDS;
 
    return nvc0_create_texture_view(pipe, &res->base, &templ, flags, target);
 }
@@ -769,21 +766,21 @@ static const uint16_t nve4_suldp_lib_offset[PIPE_FORMAT_COUNT];
 
 static void
 nvc0_get_surface_dims(struct pipe_image_view *view, int *width, int *height,
                       int *depth)
 {
    struct nv04_resource *res = nv04_resource(view->resource);
    int level;
 
    *width = *height = *depth = 1;
    if (res->base.target == PIPE_BUFFER) {
-      *width = view->u.buf.last_element - view->u.buf.first_element + 1;
+      *width = view->u.buf.size / util_format_get_blocksize(view->format);
       return;
    }
 
    level = view->u.tex.level;
    *width = u_minify(view->resource->width0, level);
    *height = u_minify(view->resource->height0, level);
    *depth = u_minify(view->resource->depth0, level);
 
    switch (res->base.target) {
    case PIPE_TEXTURE_1D_ARRAY:
@@ -800,31 +797,26 @@ nvc0_get_surface_dims(struct pipe_image_view *view, int *width, int *height,
    default:
       assert(!"unexpected texture target");
       break;
    }
 }
 
 void
 nvc0_mark_image_range_valid(const struct pipe_image_view *view)
 {
    struct nv04_resource *res = (struct nv04_resource *)view->resource;
-   const struct util_format_description *desc;
-   unsigned stride;
 
    assert(view->resource->target == PIPE_BUFFER);
 
-   desc = util_format_description(view->format);
-   stride = desc->block.bits / 8;
-
    util_range_add(&res->valid_buffer_range,
-                  stride * (view->u.buf.first_element),
-                  stride * (view->u.buf.last_element + 1));
+                  view->u.buf.offset,
+                  view->u.buf.offset + view->u.buf.size);
 }
 
 void
 nve4_set_surface_info(struct nouveau_pushbuf *push,
                       struct pipe_image_view *view,
                       struct nvc0_context *nvc0)
 {
    struct nvc0_screen *screen = nvc0->screen;
    struct nv04_resource *res;
    uint64_t address;
@@ -896,23 +888,21 @@ nve4_set_surface_info(struct nouveau_pushbuf *push,
    default:
       break;
    }
 #else
    info[1] |= log2cpp << 16;
    info[1] |=  0x4000;
    info[1] |= (0x0f00 & nve4_su_format_aux_map[view->format]);
 #endif
 
    if (res->base.target == PIPE_BUFFER) {
-      unsigned blocksize = util_format_get_blocksize(view->format);
-
-      address += view->u.buf.first_element * blocksize;
+      address += view->u.buf.offset;
 
       info[0]  = address >> 8;
       info[2]  = width - 1;
       info[2] |= (0xff & nve4_su_format_aux_map[view->format]) << 22;
       info[3]  = 0;
       info[4]  = 0;
       info[5]  = 0;
       info[6]  = 0;
       info[7]  = 0;
       info[14] = 0;
@@ -1023,21 +1013,21 @@ nvc0_validate_suf(struct nvc0_context *nvc0, int s)
          else
             rt = (rt << 4) | (0x14 << 12);
 
          /* get surface dimensions based on the target. */
          nvc0_get_surface_dims(view, &width, &height, &depth);
 
          address = res->address;
          if (res->base.target == PIPE_BUFFER) {
             unsigned blocksize = util_format_get_blocksize(view->format);
 
-            address += view->u.buf.first_element * blocksize;
+            address += view->u.buf.offset;
             assert(!(address & 0xff));
 
             if (view->access & PIPE_IMAGE_ACCESS_WRITE)
                nvc0_mark_image_range_valid(view);
 
             PUSH_DATAh(push, address);
             PUSH_DATA (push, address);
             PUSH_DATA (push, align(width * blocksize, 0x100));
             PUSH_DATA (push, NVC0_3D_IMAGE_HEIGHT_LINEAR | 1);
             PUSH_DATA (push, rt);
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index a3e4564..0e026e9 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -593,31 +593,26 @@ si_disable_shader_image(struct si_context *ctx, unsigned shader, unsigned slot)
 		images->enabled_mask &= ~(1u << slot);
 		descs->dirty_mask |= 1u << slot;
 		ctx->descriptors_dirty |= 1u << si_image_descriptors_idx(shader);
 	}
 }
 
 static void
 si_mark_image_range_valid(const struct pipe_image_view *view)
 {
 	struct r600_resource *res = (struct r600_resource *)view->resource;
-	const struct util_format_description *desc;
-	unsigned stride;
 
 	assert(res && res->b.b.target == PIPE_BUFFER);
 
-	desc = util_format_description(view->format);
-	stride = desc->block.bits / 8;
-
 	util_range_add(&res->valid_buffer_range,
-		       stride * (view->u.buf.first_element),
-		       stride * (view->u.buf.last_element + 1));
+		       view->u.buf.offset,
+		       view->u.buf.offset + view->u.buf.size);
 }
 
 static void si_set_shader_image(struct si_context *ctx,
 				unsigned shader,
 				unsigned slot, const struct pipe_image_view *view)
 {
 	struct si_screen *screen = ctx->screen;
 	struct si_images_info *images = &ctx->images[shader];
 	struct si_descriptors *descs = si_image_descriptors(ctx, shader);
 	struct r600_resource *res;
@@ -634,25 +629,22 @@ static void si_set_shader_image(struct si_context *ctx,
 
 	si_sampler_view_add_buffer(ctx, &res->b.b,
 				   RADEON_USAGE_READWRITE, false, true);
 
 	if (res->b.b.target == PIPE_BUFFER) {
 		if (view->access & PIPE_IMAGE_ACCESS_WRITE)
 			si_mark_image_range_valid(view);
 
 		si_make_buffer_descriptor(screen, res,
 					  view->format,
-					  view->u.buf.first_element *
-					  util_format_get_blocksize(view->format),
-					  (view->u.buf.last_element -
-					   view->u.buf.first_element + 1) *
-					  util_format_get_blocksize(view->format),
+					  view->u.buf.offset,
+					  view->u.buf.size,
 					  descs->list + slot * 8);
 		images->compressed_colortex_mask &= ~(1 << slot);
 	} else {
 		static const unsigned char swizzle[4] = { 0, 1, 2, 3 };
 		struct r600_texture *tex = (struct r600_texture *)res;
 		unsigned level = view->u.tex.level;
 		unsigned width, height, depth;
 		uint32_t *desc = descs->list + slot * 8;
 		bool uses_dcc = tex->dcc_offset &&
 				tex->surface.level[level].dcc_enabled;
diff --git a/src/gallium/drivers/softpipe/sp_image.c b/src/gallium/drivers/softpipe/sp_image.c
index 0be11cb..d5547e2 100644
--- a/src/gallium/drivers/softpipe/sp_image.c
+++ b/src/gallium/drivers/softpipe/sp_image.c
@@ -32,21 +32,21 @@
  * first element for a buffer or layer/level for texture.
  */
 static uint32_t
 get_image_offset(const struct softpipe_resource *spr,
                  const struct pipe_image_view *iview,
                  enum pipe_format format, unsigned r_coord)
 {
    int base_layer = 0;
 
    if (spr->base.target == PIPE_BUFFER)
-      return iview->u.buf.first_element * util_format_get_blocksize(format);
+      return iview->u.buf.offset;
 
    if (spr->base.target == PIPE_TEXTURE_1D_ARRAY ||
        spr->base.target == PIPE_TEXTURE_2D_ARRAY ||
        spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
        spr->base.target == PIPE_TEXTURE_CUBE ||
        spr->base.target == PIPE_TEXTURE_3D)
       base_layer = r_coord + iview->u.tex.first_layer;
    return softpipe_get_tex_image_offset(spr, iview->u.tex.level, base_layer);
 }
 
@@ -146,21 +146,21 @@ has_compat_target(unsigned pipe_target, unsigned tgsi_target)
 static bool
 get_dimensions(const struct pipe_image_view *iview,
                const struct softpipe_resource *spr,
                unsigned tgsi_tex_instr,
                enum pipe_format pformat,
                unsigned *width,
                unsigned *height,
                unsigned *depth)
 {
    if (tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
-      *width = iview->u.buf.last_element - iview->u.buf.first_element + 1;
+      *width = iview->u.buf.size / util_format_get_blocksize(pformat);
       *height = 1;
       *depth = 1;
       /*
        * Bounds check the buffer size from the view
        * and the buffer size from the underlying buffer.
        */
       if (util_format_get_stride(pformat, *width) >
           util_format_get_stride(spr->base.format, spr->base.width0))
          return false;
    } else {
@@ -745,21 +745,21 @@ sp_tgsi_get_dims(const struct tgsi_image *image,
    int level;
 
    if (params->unit >= PIPE_MAX_SHADER_IMAGES)
       return;
    iview = &sp_img->sp_iview[params->unit];
    spr = (struct softpipe_resource *)iview->resource;
    if (!spr)
       return;
 
    if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
-      dims[0] = iview->u.buf.last_element - iview->u.buf.first_element + 1;
+      dims[0] = iview->u.buf.size / util_format_get_blocksize(iview->format);
       dims[1] = dims[2] = dims[3] = 0;
       return;
    }
 
    level = iview->u.tex.level;
    dims[0] = u_minify(spr->base.width0, level);
    switch (params->tgsi_tex_instr) {
    case TGSI_TEXTURE_1D_ARRAY:
       dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
       /* fallthrough */
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index d80037a..c5740d0 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -753,22 +753,22 @@ void trace_dump_image_view(const struct pipe_image_view *state)
    trace_dump_struct_begin("pipe_image_view");
    trace_dump_member(resource_ptr, state, resource);
    trace_dump_member(uint, state, format);
    trace_dump_member(uint, state, access);
 
    trace_dump_member_begin("u");
    trace_dump_struct_begin(""); /* anonymous */
    if (state->resource->target == PIPE_BUFFER) {
       trace_dump_member_begin("buf");
       trace_dump_struct_begin(""); /* anonymous */
-      trace_dump_member(uint, &state->u.buf, first_element);
-      trace_dump_member(uint, &state->u.buf, last_element);
+      trace_dump_member(uint, &state->u.buf, offset);
+      trace_dump_member(uint, &state->u.buf, size);
       trace_dump_struct_end(); /* anonymous */
       trace_dump_member_end(); /* buf */
    } else {
       trace_dump_member_begin("tex");
       trace_dump_struct_begin(""); /* anonymous */
       trace_dump_member(uint, &state->u.tex, first_layer);
       trace_dump_member(uint, &state->u.tex, last_layer);
       trace_dump_member(uint, &state->u.tex, level);
       trace_dump_struct_end(); /* anonymous */
       trace_dump_member_end(); /* tex */
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 1fd6353..ebd0337 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -449,22 +449,22 @@ struct pipe_image_view
    enum pipe_format format;      /**< typed PIPE_FORMAT_x */
    unsigned access;              /**< PIPE_IMAGE_ACCESS_x */
 
    union {
       struct {
          unsigned first_layer:16;     /**< first layer to use for array textures */
          unsigned last_layer:16;      /**< last layer to use for array textures */
          unsigned level:8;            /**< mipmap level to use */
       } tex;
       struct {
-         unsigned first_element;
-         unsigned last_element;
+         unsigned offset;   /**< offset in bytes */
+         unsigned size;     /**< size of the accessible sub-range in bytes */
       } buf;
    } u;
 };
 
 
 /**
  * Subregion of 1D/2D/3D image resource.
  */
 struct pipe_box
 {
diff --git a/src/mesa/state_tracker/st_atom_image.c b/src/mesa/state_tracker/st_atom_image.c
index e80fc14..4d76ac9 100644
--- a/src/mesa/state_tracker/st_atom_image.c
+++ b/src/mesa/state_tracker/st_atom_image.c
@@ -81,33 +81,27 @@ st_bind_images(struct st_context *st, struct gl_linked_shader *shader,
          break;
       case GL_READ_WRITE:
          img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
          break;
       default:
          unreachable("bad gl_image_unit::Access");
       }
 
       if (stObj->pt->target == PIPE_BUFFER) {
          unsigned base, size;
-         unsigned f, n;
-         const struct util_format_description *desc
-            = util_format_description(img->format);
 
          base = stObj->base.BufferOffset;
          assert(base < stObj->pt->width0);
          size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
 
-         f = (base / (desc->block.bits / 8)) * desc->block.width;
-         n = (size / (desc->block.bits / 8)) * desc->block.width;
-         assert(n > 0);
-         img->u.buf.first_element = f;
-         img->u.buf.last_element  = f + (n - 1);
+         img->u.buf.offset = base;
+         img->u.buf.size = size;
       } else {
          img->u.tex.level = u->Level + stObj->base.MinLevel;
          if (stObj->pt->target == PIPE_TEXTURE_3D) {
             if (u->Layered) {
                img->u.tex.first_layer = 0;
                img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
             } else {
                img->u.tex.first_layer = u->_Layer;
                img->u.tex.last_layer = u->_Layer;
             }
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index 8eb839d..3cfdf78 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -185,22 +185,23 @@ try_pbo_readpixels(struct st_context *st, struct st_renderbuffer *strb,
    }
 
    /* Set up destination image */
    {
       struct pipe_image_view image;
 
       memset(&image, 0, sizeof(image));
       image.resource = addr.buffer;
       image.format = dst_format;
       image.access = PIPE_IMAGE_ACCESS_WRITE;
-      image.u.buf.first_element = addr.first_element;
-      image.u.buf.last_element = addr.last_element;
+      image.u.buf.offset = addr.first_element * addr.bytes_per_pixel;
+      image.u.buf.size = (addr.last_element - addr.first_element + 1) *
+                         addr.bytes_per_pixel;
 
       cso_set_shader_images(cso, PIPE_SHADER_FRAGMENT, 0, 1, &image);
    }
 
    /* Set up no-attachment framebuffer */
    memset(&fb, 0, sizeof(fb));
    fb.width = surface->width;
    fb.height = surface->height;
    fb.samples = 1;
    fb.layers = 1;
-- 
2.7.4



More information about the mesa-dev mailing list