From: Marek Olšák <marek.ol...@amd.com>

This is required by OpenGL. Our hardware supports this.

Example: Bind RGBA32F with offset = 4 bytes.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97305
---
 src/gallium/auxiliary/util/u_dump_state.c        |  4 ++--
 src/gallium/docs/source/screen.rst               |  4 ++--
 src/gallium/drivers/freedreno/a3xx/fd3_emit.c    |  3 +--
 src/gallium/drivers/freedreno/a3xx/fd3_texture.c |  3 +--
 src/gallium/drivers/freedreno/a4xx/fd4_texture.c |  7 +++----
 src/gallium/drivers/ilo/ilo_state.c              |  5 ++---
 src/gallium/drivers/llvmpipe/lp_setup.c          | 12 +++++-------
 src/gallium/drivers/llvmpipe/lp_state_sampler.c  |  8 +++-----
 src/gallium/drivers/nouveau/nv50/nv50_tex.c      |  7 +++----
 src/gallium/drivers/nouveau/nvc0/nvc0_tex.c      | 18 ++++++++++--------
 src/gallium/drivers/r600/evergreen_state.c       |  4 ++--
 src/gallium/drivers/r600/r600_state.c            |  4 ++--
 src/gallium/drivers/r600/r600_state_common.c     |  3 +--
 src/gallium/drivers/radeonsi/si_descriptors.c    |  7 +++++--
 src/gallium/drivers/radeonsi/si_state.c          | 10 +++++-----
 src/gallium/drivers/radeonsi/si_state.h          |  2 +-
 src/gallium/drivers/softpipe/sp_state_sampler.c  |  8 +++-----
 src/gallium/drivers/softpipe/sp_tex_sample.c     | 13 +++++++++----
 src/gallium/drivers/svga/svga_state_sampler.c    |  8 +++++---
 src/gallium/drivers/trace/tr_dump_state.c        |  4 ++--
 src/gallium/drivers/virgl/virgl_encode.c         |  7 +++++--
 src/gallium/include/pipe/p_state.h               |  4 ++--
 src/mesa/state_tracker/st_atom_texture.c         | 13 ++++---------
 src/mesa/state_tracker/st_cb_texture.c           |  5 +++--
 24 files changed, 81 insertions(+), 82 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_dump_state.c 
b/src/gallium/auxiliary/util/u_dump_state.c
index bad38fb..4568dc6 100644
--- a/src/gallium/auxiliary/util/u_dump_state.c
+++ b/src/gallium/auxiliary/util/u_dump_state.c
@@ -743,22 +743,22 @@ util_dump_sampler_view(FILE *stream, const struct 
pipe_sampler_view *state)
       return;
    }
 
    util_dump_struct_begin(stream, "pipe_sampler_view");
 
    util_dump_member(stream, enum_tex_target, state, target);
    util_dump_member(stream, format, state, format);
    util_dump_member(stream, ptr, state, texture);
 
    if (state->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.last_level);
       util_dump_member(stream, uint, state, u.tex.last_level);
    }
 
    util_dump_member(stream, uint, state, swizzle_r);
    util_dump_member(stream, uint, state, swizzle_g);
diff --git a/src/gallium/docs/source/screen.rst 
b/src/gallium/docs/source/screen.rst
index 34f2e72..3199e3c 100644
--- a/src/gallium/docs/source/screen.rst
+++ b/src/gallium/docs/source/screen.rst
@@ -129,22 +129,22 @@ The integer capabilities:
   pipe_draw_info::start_instance.
 * ``PIPE_CAP_QUERY_TIMESTAMP``: Whether PIPE_QUERY_TIMESTAMP and
   the pipe_screen::get_timestamp hook are implemented.
 * ``PIPE_CAP_TEXTURE_MULTISAMPLE``: Whether all MSAA resources supported
   for rendering are also supported for texturing.
 * ``PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT``: The minimum alignment that should be
   expected for a pointer returned by transfer_map if the resource is
   PIPE_BUFFER. In other words, the pointer returned by transfer_map is
   always aligned to this value.
 * ``PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT``: Describes the required
-  alignment for pipe_sampler_view::u.buf.first_element, in bytes.
-  If a driver does not support first/last_element, it should return 0.
+  alignment for pipe_sampler_view::u.buf.offset, in bytes.
+  If a driver does not support offset/size, it should return 0.
 * ``PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY``: Whether the driver only
   supports R, RG, RGB and RGBA formats for PIPE_BUFFER sampler views.
   When this is the case it should be assumed that the swizzle parameters
   in the sampler view have no effect.
 * ``PIPE_CAP_TGSI_TEXCOORD``: This CAP describes a hw limitation.
   If true, the hardware cannot replace arbitrary shader inputs with sprite
   coordinates and hence the inputs that are desired to be replaceable must
   be declared with TGSI_SEMANTIC_TEXCOORD instead of TGSI_SEMANTIC_GENERIC.
   The rasterizer's sprite_coord_enable state therefore also applies to the
   TEXCOORD semantic.
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c 
b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
index 0fb2ee1..3466a0d 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
@@ -199,22 +199,21 @@ emit_textures(struct fd_context *ctx, struct 
fd_ringbuffer *ring,
                for (i = 0; i < tex->num_textures; i++) {
                        static const struct fd3_pipe_sampler_view dummy_view = {
                                        .base.target = PIPE_TEXTURE_1D, /* 
anything !PIPE_BUFFER */
                                        .base.u.tex.first_level = 1,
                        };
                        const struct fd3_pipe_sampler_view *view = 
tex->textures[i] ?
                                        fd3_pipe_sampler_view(tex->textures[i]) 
:
                                        &dummy_view;
                        struct fd_resource *rsc = 
fd_resource(view->base.texture);
                        if (rsc && rsc->base.b.target == PIPE_BUFFER) {
-                               OUT_RELOC(ring, rsc->bo, 
view->base.u.buf.first_element *
-                                                 
util_format_get_blocksize(view->base.format), 0, 0);
+                               OUT_RELOC(ring, rsc->bo, 
view->base.u.buf.offset, 0, 0);
                                j = 1;
                        } else {
                                unsigned start = 
fd_sampler_first_level(&view->base);
                                unsigned end   = 
fd_sampler_last_level(&view->base);
 
                                for (j = 0; j < (end - start + 1); j++) {
                                        struct fd_resource_slice *slice =
                                                fd_resource_slice(rsc, j + 
start);
                                        OUT_RELOC(ring, rsc->bo, slice->offset, 
0, 0);
                                }
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c 
b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
index 81336bf..ea2d341 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
@@ -234,22 +234,21 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct 
pipe_resource *prsc,
                        fd3_tex_swiz(cso->format, cso->swizzle_r, 
cso->swizzle_g,
                                                cso->swizzle_b, cso->swizzle_a);
 
        if (util_format_is_srgb(cso->format))
                so->texconst0 |= A3XX_TEX_CONST_0_SRGB;
 
        if (prsc->target == PIPE_BUFFER) {
                lvl = 0;
                so->texconst1 =
                        
A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
-                       A3XX_TEX_CONST_1_WIDTH(cso->u.buf.last_element -
-                                                                  
cso->u.buf.first_element + 1) |
+                       A3XX_TEX_CONST_1_WIDTH(cso->u.buf.size / 
util_format_get_blocksize(cso->format)) |
                        A3XX_TEX_CONST_1_HEIGHT(1);
        } else {
                unsigned miplevels;
 
                lvl = fd_sampler_first_level(cso);
                miplevels = fd_sampler_last_level(cso) - lvl;
 
                so->texconst0 |= A3XX_TEX_CONST_0_MIPLVLS(miplevels);
                so->texconst1 =
                        
A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c 
b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
index da8c681..e62c732 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
@@ -242,31 +242,30 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct 
pipe_resource *prsc,
                fd4_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
                                cso->swizzle_b, cso->swizzle_a);
 
        if (util_format_is_srgb(cso->format)) {
                if (use_astc_srgb_workaround(pctx, cso->format))
                        so->astc_srgb = true;
                so->texconst0 |= A4XX_TEX_CONST_0_SRGB;
        }
 
        if (cso->target == PIPE_BUFFER) {
-               unsigned elements = cso->u.buf.last_element -
-                       cso->u.buf.first_element + 1;
+               unsigned elements = cso->u.buf.size / 
util_format_get_blocksize(cso->format);
+
                lvl = 0;
                so->texconst1 =
                        A4XX_TEX_CONST_1_WIDTH(elements) |
                        A4XX_TEX_CONST_1_HEIGHT(1);
                so->texconst2 =
                        
A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(cso->format)) |
                        A4XX_TEX_CONST_2_PITCH(elements * rsc->cpp);
-               so->offset = cso->u.buf.first_element *
-                       util_format_get_blocksize(cso->format);
+               so->offset = cso->u.buf.offset;
        } else {
                unsigned miplevels;
 
                lvl = fd_sampler_first_level(cso);
                miplevels = fd_sampler_last_level(cso) - lvl;
                layers = cso->u.tex.last_layer - cso->u.tex.first_layer + 1;
 
                so->texconst0 |= A4XX_TEX_CONST_0_MIPLVLS(miplevels);
                so->texconst1 =
                        A4XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
diff --git a/src/gallium/drivers/ilo/ilo_state.c 
b/src/gallium/drivers/ilo/ilo_state.c
index 4f1002e..7693133 100644
--- a/src/gallium/drivers/ilo/ilo_state.c
+++ b/src/gallium/drivers/ilo/ilo_state.c
@@ -2008,23 +2008,22 @@ ilo_create_sampler_view(struct pipe_context *pipe,
    pipe_reference_init(&view->base.reference, 1);
    view->base.texture = NULL;
    pipe_resource_reference(&view->base.texture, res);
    view->base.context = pipe;
 
    if (res->target == PIPE_BUFFER) {
       struct ilo_state_surface_buffer_info info;
 
       memset(&info, 0, sizeof(info));
       info.vma = ilo_resource_get_vma(res);
-      info.offset = templ->u.buf.first_element * info.struct_size;
-      info.size = (templ->u.buf.last_element -
-            templ->u.buf.first_element + 1) * info.struct_size;
+      info.offset = templ->u.buf.offset;
+      info.size = templ->u.buf.size;
       info.access = ILO_STATE_SURFACE_ACCESS_SAMPLER;
       info.format = ilo_format_translate_color(dev, templ->format);
       info.format_size = util_format_get_blocksize(templ->format);
       info.struct_size = info.format_size;
       info.readonly = true;
 
       ilo_state_surface_init_for_buffer(&view->surface, dev, &info);
    } else {
       struct ilo_texture *tex = ilo_texture(res);
       struct ilo_state_surface_image_info info;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c 
b/src/gallium/drivers/llvmpipe/lp_setup.c
index 0a45db9..f622b19 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -882,36 +882,34 @@ lp_setup_set_fragment_sampler_views(struct 
lp_setup_context *setup,
                      if (view->target == PIPE_TEXTURE_CUBE ||
                          view->target == PIPE_TEXTURE_CUBE_ARRAY) {
                         assert(jit_tex->depth % 6 == 0);
                      }
                      assert(view->u.tex.first_layer <= view->u.tex.last_layer);
                      assert(view->u.tex.last_layer < res->array_size);
                   }
                }
                else {
                   /*
-                   * For buffers, we don't have first_element, instead adjust
-                   * last_element (stored as width) plus the base pointer.
+                   * For buffers, we don't have "offset", instead adjust
+                   * the size (stored as width) plus the base pointer.
                    */
                   unsigned view_blocksize = 
util_format_get_blocksize(view->format);
                   /* probably don't really need to fill that out */
                   jit_tex->mip_offsets[0] = 0;
                   jit_tex->row_stride[0] = 0;
                   jit_tex->img_stride[0] = 0;
 
                   /* everything specified in number of elements here. */
-                  jit_tex->width = view->u.buf.last_element - 
view->u.buf.first_element + 1;
-                  jit_tex->base = (uint8_t *)jit_tex->base + 
view->u.buf.first_element *
-                                  view_blocksize;
+                  jit_tex->width = view->u.buf.size / view_blocksize;
+                  jit_tex->base = (uint8_t *)jit_tex->base + 
view->u.buf.offset;
                   /* XXX Unsure if we need to sanitize parameters? */
-                  assert(view->u.buf.first_element <= 
view->u.buf.last_element);
-                  assert(view->u.buf.last_element * view_blocksize < 
res->width0);
+                  assert(view->u.buf.offset + view->u.buf.size <= res->width0);
                }
             }
          }
          else {
             /* display target texture/surface */
             /*
              * XXX: Where should this be unmapped?
              */
             struct llvmpipe_screen *screen = llvmpipe_screen(res->screen);
             struct sw_winsys *winsys = screen->winsys;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c 
b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
index 4441f2a..665cd9e 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
@@ -301,25 +301,23 @@ prepare_shader_sampling(
             }
             else {
                unsigned view_blocksize = 
util_format_get_blocksize(view->format);
                addr = lp_tex->data;
                /* probably don't really need to fill that out */
                mip_offsets[0] = 0;
                row_stride[0] = 0;
                img_stride[0] = 0;
 
                /* everything specified in number of elements here. */
-               width0 = view->u.buf.last_element - view->u.buf.first_element + 
1;
-               addr = (uint8_t *)addr + view->u.buf.first_element *
-                               view_blocksize;
-               assert(view->u.buf.first_element <= view->u.buf.last_element);
-               assert(view->u.buf.last_element * view_blocksize < res->width0);
+               width0 = view->u.buf.size / view_blocksize;
+               addr = (uint8_t *)addr + view->u.buf.offset;
+               assert(view->u.buf.offset + view->u.buf.size <= res->width0);
             }
          }
          else {
             /* display target texture/surface */
             /*
              * XXX: Where should this be unmapped?
              */
             struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen);
             struct sw_winsys *winsys = screen->winsys;
             addr = winsys->displaytarget_map(winsys, lp_tex->dt,
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_tex.c 
b/src/gallium/drivers/nouveau/nv50/nv50_tex.c
index 953ab8f..ad23018 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_tex.c
@@ -124,25 +124,25 @@ nv50_create_texture_view(struct pipe_context *pipe,
    tic[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR;
 
    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
       tic[2] |= G80_TIC_2_SRGB_CONVERSION;
 
    if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
       tic[2] |= G80_TIC_2_NORMALIZED_COORDS;
 
    if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
       if (target == PIPE_BUFFER) {
-         addr += view->pipe.u.buf.first_element * desc->block.bits / 8;
+         addr += view->pipe.u.buf.offset;
          tic[2] |= G80_TIC_2_LAYOUT_PITCH | 
G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER;
          tic[3] = 0;
          tic[4] = /* width */
-            view->pipe.u.buf.last_element - view->pipe.u.buf.first_element + 1;
+            view->pipe.u.buf.size / (desc->block.bits / 8);
          tic[5] = 0;
       } else {
          tic[2] |= G80_TIC_2_LAYOUT_PITCH | 
G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
          tic[3] = mt->level[0].pitch;
          tic[4] = mt->base.base.width0;
          tic[5] = (1 << 16) | (mt->base.base.height0);
       }
       tic[6] =
       tic[7] = 0;
       tic[1] = addr;
@@ -217,22 +217,21 @@ nv50_create_texture_view(struct pipe_context *pipe,
    return &view->pipe;
 }
 
 static void
 nv50_update_tic(struct nv50_context *nv50, struct nv50_tic_entry *tic,
                 struct nv04_resource *res)
 {
    uint64_t address = res->address;
    if (res->base.target != PIPE_BUFFER)
       return;
-   address += tic->pipe.u.buf.first_element *
-      util_format_get_blocksize(tic->pipe.format);
+   address += tic->pipe.u.buf.offset;
    if (tic->tic[1] == (uint32_t)address &&
        (tic->tic[2] & 0xff) == address >> 32)
       return;
 
    nv50_screen_tic_unlock(nv50->screen, tic);
    tic->id = -1;
    tic->tic[1] = address;
    tic->tic[2] &= 0xffffff00;
    tic->tic[2] |= address >> 32;
 }
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c 
b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
index 40a9c93..b6e0ba8 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
@@ -125,23 +125,23 @@ gm107_create_texture_view(struct pipe_context *pipe,
 
    if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
       tic[5] = GM107_TIC2_5_NORMALIZED_COORDS;
    else
       tic[5] = 0;
 
    /* check for linear storage type */
    if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
       if (texture->target == PIPE_BUFFER) {
          assert(!(tic[5] & GM107_TIC2_5_NORMALIZED_COORDS));
-         width = view->pipe.u.buf.last_element - 
view->pipe.u.buf.first_element;
+         width = view->pipe.u.buf.size / (desc->block.bits / 8) - 1;
          address +=
-            view->pipe.u.buf.first_element * desc->block.bits / 8;
+            view->pipe.u.buf.offset;
          tic[2]  = GM107_TIC2_2_HEADER_VERSION_ONE_D_BUFFER;
          tic[3] |= width >> 16;
          tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D_BUFFER;
          tic[4] |= width & 0xffff;
       } else {
          assert(!(mt->level[0].pitch & 0x1f));
          /* must be 2D texture without mip maps */
          tic[2]  = GM107_TIC2_2_HEADER_VERSION_PITCH;
          tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
          tic[3] |= mt->level[0].pitch >> 5;
@@ -252,22 +252,25 @@ 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.first_element = view->u.buf.first_element;
-      templ.u.buf.last_element = view->u.buf.last_element;
+      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);
    } 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);
 }
@@ -337,25 +340,25 @@ gf100_create_texture_view(struct pipe_context *pipe,
       tic[2] |= G80_TIC_2_SRGB_CONVERSION;
 
    if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
       tic[2] |= G80_TIC_2_NORMALIZED_COORDS;
 
    /* check for linear storage type */
    if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
       if (texture->target == PIPE_BUFFER) {
          assert(!(tic[2] & G80_TIC_2_NORMALIZED_COORDS));
          address +=
-            view->pipe.u.buf.first_element * desc->block.bits / 8;
+            view->pipe.u.buf.offset;
          tic[2] |= G80_TIC_2_LAYOUT_PITCH | 
G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER;
          tic[3] = 0;
          tic[4] = /* width */
-            view->pipe.u.buf.last_element - view->pipe.u.buf.first_element + 1;
+            view->pipe.u.buf.size / (desc->block.bits / 8);
          tic[5] = 0;
       } else {
          /* must be 2D texture without mip maps */
          tic[2] |= G80_TIC_2_LAYOUT_PITCH | 
G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
          tic[3] = mt->level[0].pitch;
          tic[4] = mt->base.base.width0;
          tic[5] = (1 << 16) | mt->base.base.height0;
       }
       tic[6] =
       tic[7] = 0;
@@ -449,22 +452,21 @@ nvc0_create_texture_view(struct pipe_context *pipe,
    return gf100_create_texture_view(pipe, texture, templ, flags, target);
 }
 
 void
 nvc0_update_tic(struct nvc0_context *nvc0, struct nv50_tic_entry *tic,
                 struct nv04_resource *res)
 {
    uint64_t address = res->address;
    if (res->base.target != PIPE_BUFFER)
       return;
-   address += tic->pipe.u.buf.first_element *
-      util_format_get_blocksize(tic->pipe.format);
+   address += tic->pipe.u.buf.offset;
    if (tic->tic[1] == (uint32_t)address &&
        (tic->tic[2] & 0xff) == address >> 32)
       return;
 
    nvc0_screen_tic_unlock(nvc0->screen, tic);
    tic->id = -1;
    tic->tic[1] = address;
    tic->tic[2] &= 0xffffff00;
    tic->tic[2] |= address >> 32;
 }
diff --git a/src/gallium/drivers/r600/evergreen_state.c 
b/src/gallium/drivers/r600/evergreen_state.c
index 7611520..3d1a19d 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -606,22 +606,22 @@ texture_buffer_sampler_view(struct r600_context *rctx,
                            unsigned width0, unsigned height0)
                            
 {
        struct r600_texture *tmp = (struct r600_texture*)view->base.texture;
        uint64_t va;
        int stride = util_format_get_blocksize(view->base.format);
        unsigned format, num_format, format_comp, endian;
        unsigned swizzle_res;
        unsigned char swizzle[4];
        const struct util_format_description *desc;
-       unsigned offset = view->base.u.buf.first_element * stride;
-       unsigned size = (view->base.u.buf.last_element - 
view->base.u.buf.first_element + 1) * stride;
+       unsigned offset = view->base.u.buf.offset;
+       unsigned size = view->base.u.buf.size;
 
        swizzle[0] = view->base.swizzle_r;
        swizzle[1] = view->base.swizzle_g;
        swizzle[2] = view->base.swizzle_b;
        swizzle[3] = view->base.swizzle_a;
 
        r600_vertex_data_type(view->base.format,
                              &format, &num_format, &format_comp,
                              &endian);
 
diff --git a/src/gallium/drivers/r600/r600_state.c 
b/src/gallium/drivers/r600/r600_state.c
index 046573f..62b1c2c 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -624,22 +624,22 @@ static void *r600_create_sampler_state(struct 
pipe_context *ctx,
 }
 
 static struct pipe_sampler_view *
 texture_buffer_sampler_view(struct r600_pipe_sampler_view *view,
                            unsigned width0, unsigned height0)
                            
 {
        struct r600_texture *tmp = (struct r600_texture*)view->base.texture;
        int stride = util_format_get_blocksize(view->base.format);
        unsigned format, num_format, format_comp, endian;
-       uint64_t offset = view->base.u.buf.first_element * stride;
-       unsigned size = (view->base.u.buf.last_element - 
view->base.u.buf.first_element + 1) * stride;
+       uint64_t offset = view->base.u.buf.offset;
+       unsigned size = view->base.u.buf.size;
 
        r600_vertex_data_type(view->base.format,
                              &format, &num_format, &format_comp,
                              &endian);
 
        view->tex_resource = &tmp->resource;
        view->skip_mip_address_reloc = true;
 
        view->tex_resource_words[0] = offset;
        view->tex_resource_words[1] = size - 1;
diff --git a/src/gallium/drivers/r600/r600_state_common.c 
b/src/gallium/drivers/r600/r600_state_common.c
index 11ef925..9008a4a 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -2824,22 +2824,21 @@ static void r600_invalidate_buffer(struct pipe_context 
*ctx, struct pipe_resourc
                        }
                }
                if (found) {
                        r600_constant_buffers_dirty(rctx, state);
                }
        }
 
        /* Texture buffer objects - update the virtual addresses in 
descriptors. */
        LIST_FOR_EACH_ENTRY(view, &rctx->b.texture_buffers, list) {
                if (view->base.texture == &rbuffer->b.b) {
-                       unsigned stride = 
util_format_get_blocksize(view->base.format);
-                       uint64_t offset = 
(uint64_t)view->base.u.buf.first_element * stride;
+                       uint64_t offset = view->base.u.buf.offset;
                        uint64_t va = rbuffer->gpu_address + offset;
 
                        view->tex_resource_words[0] = va;
                        view->tex_resource_words[2] &= C_038008_BASE_ADDRESS_HI;
                        view->tex_resource_words[2] |= 
S_038008_BASE_ADDRESS_HI(va >> 32);
                }
        }
        /* Texture buffer objects - make bindings dirty if needed. */
        for (shader = 0; shader < PIPE_SHADER_TYPES; shader++) {
                struct r600_samplerview_state *state = 
&rctx->samplers[shader].views;
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c 
b/src/gallium/drivers/radeonsi/si_descriptors.c
index f03a895..a3e4564 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -634,22 +634,25 @@ 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,
-                                         view->u.buf.last_element,
+                                         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),
                                          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/radeonsi/si_state.c 
b/src/gallium/drivers/radeonsi/si_state.c
index 8d9fe53..7e63d48 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2637,38 +2637,38 @@ static void si_set_min_samples(struct pipe_context 
*ctx, unsigned min_samples)
  * Samplers
  */
 
 /**
  * Build the sampler view descriptor for a buffer texture.
  * @param state 256-bit descriptor; only the high 128 bits are filled in
  */
 void
 si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
                          enum pipe_format format,
-                         unsigned first_element, unsigned last_element,
+                         unsigned offset, unsigned size,
                          uint32_t *state)
 {
        const struct util_format_description *desc;
        int first_non_void;
        uint64_t va;
        unsigned stride;
        unsigned num_records;
        unsigned num_format, data_format;
 
        desc = util_format_description(format);
        first_non_void = util_format_get_first_non_void_channel(format);
        stride = desc->block.bits / 8;
-       va = buf->gpu_address + first_element * stride;
+       va = buf->gpu_address + offset;
        num_format = si_translate_buffer_numformat(&screen->b.b, desc, 
first_non_void);
        data_format = si_translate_buffer_dataformat(&screen->b.b, desc, 
first_non_void);
 
-       num_records = last_element + 1 - first_element;
+       num_records = size / stride;
        num_records = MIN2(num_records, buf->b.b.width0 / stride);
 
        if (screen->b.chip_class >= VI)
                num_records *= stride;
 
        state[4] = va;
        state[5] = S_008F04_BASE_ADDRESS_HI(va >> 32) |
                   S_008F04_STRIDE(stride);
        state[6] = num_records;
        state[7] = S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) |
@@ -2953,22 +2953,22 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
            state->format == PIPE_FORMAT_S8X24_UINT ||
            state->format == PIPE_FORMAT_X32_S8X24_UINT ||
            state->format == PIPE_FORMAT_S8_UINT)
                view->is_stencil_sampler = true;
 
        /* Buffer resource. */
        if (texture->target == PIPE_BUFFER) {
                si_make_buffer_descriptor(sctx->screen,
                                          (struct r600_resource *)texture,
                                          state->format,
-                                         state->u.buf.first_element,
-                                         state->u.buf.last_element,
+                                         state->u.buf.offset,
+                                         state->u.buf.size,
                                          view->state);
 
                LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
                return &view->base;
        }
 
        state_swizzle[0] = state->swizzle_r;
        state_swizzle[1] = state->swizzle_g;
        state_swizzle[2] = state->swizzle_b;
        state_swizzle[3] = state->swizzle_a;
diff --git a/src/gallium/drivers/radeonsi/si_state.h 
b/src/gallium/drivers/radeonsi/si_state.h
index b574c2e..f4f7575 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -306,21 +306,21 @@ void si_set_rw_buffer(struct si_context *sctx,
 struct si_shader_selector;
 
 void si_init_atom(struct si_context *sctx, struct r600_atom *atom,
                  struct r600_atom **list_elem,
                  void (*emit_func)(struct si_context *ctx, struct r600_atom 
*state));
 void si_init_state_functions(struct si_context *sctx);
 void si_init_screen_state_functions(struct si_screen *sscreen);
 void
 si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
                          enum pipe_format format,
-                         unsigned first_element, unsigned last_element,
+                         unsigned offset, unsigned size,
                          uint32_t *state);
 void
 si_make_texture_descriptor(struct si_screen *screen,
                           struct r600_texture *tex,
                           bool sampler,
                           enum pipe_texture_target target,
                           enum pipe_format pipe_format,
                           const unsigned char state_swizzle[4],
                           unsigned first_level, unsigned last_level,
                           unsigned first_layer, unsigned last_layer,
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c 
b/src/gallium/drivers/softpipe/sp_state_sampler.c
index 0d5149c..f824743 100644
--- a/src/gallium/drivers/softpipe/sp_state_sampler.c
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -233,25 +233,23 @@ prepare_shader_sampling(
             }
             else {
                unsigned view_blocksize = 
util_format_get_blocksize(view->format);
                addr = sp_tex->data;
                /* probably don't really need to fill that out */
                mip_offsets[0] = 0;
                row_stride[0] = 0;
                img_stride[0] = 0;
 
                /* everything specified in number of elements here. */
-               width0 = view->u.buf.last_element - view->u.buf.first_element + 
1;
-               addr = (uint8_t *)addr + view->u.buf.first_element *
-                               view_blocksize;
-               assert(view->u.buf.first_element <= view->u.buf.last_element);
-               assert(view->u.buf.last_element * view_blocksize < res->width0);
+               width0 = view->u.buf.size / view_blocksize;
+               addr = (uint8_t *)addr + view->u.buf.offset;
+               assert(view->u.buf.offset + view->u.buf.size <= res->width0);
             }
          }
          else {
             /* display target texture/surface */
             /*
              * XXX: Where should this be unmapped?
              */
             struct softpipe_screen *screen = softpipe_screen(tex->screen);
             struct sw_winsys *winsys = screen->winsys;
             addr = winsys->displaytarget_map(winsys, sp_tex->dt,
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c 
b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 5998681..c457f89 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -3185,21 +3185,21 @@ convert_cube(const struct sp_sampler_view *sp_sview,
 
 static void
 sp_get_dims(const struct sp_sampler_view *sp_sview,
             int level,
             int dims[4])
 {
    const struct pipe_sampler_view *view = &sp_sview->base;
    const struct pipe_resource *texture = view->texture;
 
    if (view->target == PIPE_BUFFER) {
-      dims[0] = (view->u.buf.last_element - view->u.buf.first_element) + 1;
+      dims[0] = view->u.buf.size / util_format_get_blocksize(view->format);
       /* the other values are undefined, but let's avoid potential valgrind
        * warnings.
        */
       dims[1] = dims[2] = dims[3] = 0;
       return;
    }
 
    /* undefined according to EXT_gpu_program */
    level += view->u.tex.first_level;
    if (level > view->u.tex.last_level)
@@ -3257,31 +3257,36 @@ sp_get_texels(const struct sp_sampler_view *sp_sview,
    const float *tx;
    /* TODO write a better test for LOD */
    const unsigned level =
       sp_sview->base.target == PIPE_BUFFER ? 0 :
       CLAMP(lod[0] + sp_sview->base.u.tex.first_level,
             sp_sview->base.u.tex.first_level,
             sp_sview->base.u.tex.last_level);
    const int width = u_minify(texture->width0, level);
    const int height = u_minify(texture->height0, level);
    const int depth = u_minify(texture->depth0, level);
+   unsigned elem_size, first_element, last_element;
 
    addr.value = 0;
    addr.bits.level = level;
 
    switch (sp_sview->base.target) {
    case PIPE_BUFFER:
+      elem_size = util_format_get_blocksize(sp_sview->base.format);
+      first_element = sp_sview->base.u.buf.offset / elem_size;
+      last_element = (sp_sview->base.u.buf.offset +
+                      sp_sview->base.u.buf.size) / elem_size - 1;
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
          const int x = CLAMP(v_i[j] + offset[0] +
-                             sp_sview->base.u.buf.first_element,
-                             sp_sview->base.u.buf.first_element,
-                             sp_sview->base.u.buf.last_element);
+                             first_element,
+                             first_element,
+                             last_element);
          tx = get_texel_2d_no_border(sp_sview, addr, x, 0);
          for (c = 0; c < 4; c++) {
             rgba[c][j] = tx[c];
          }
       }
       break;
    case PIPE_TEXTURE_1D:
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
          const int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
          tx = get_texel_2d_no_border(sp_sview, addr, x,
diff --git a/src/gallium/drivers/svga/svga_state_sampler.c 
b/src/gallium/drivers/svga/svga_state_sampler.c
index 00e8fc0..2f0f838 100644
--- a/src/gallium/drivers/svga/svga_state_sampler.c
+++ b/src/gallium/drivers/svga/svga_state_sampler.c
@@ -23,20 +23,21 @@
  */
 
 
 /**
  * VGPU10 sampler and sampler view functions.
  */
 
 
 #include "pipe/p_defines.h"
 #include "util/u_bitmask.h"
+#include "util/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
 #include "svga_cmd.h"
 #include "svga_context.h"
 #include "svga_format.h"
 #include "svga_resource_buffer.h"
 #include "svga_resource_texture.h"
 #include "svga_shader.h"
@@ -118,23 +119,24 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
       }
 
       format = svga_translate_format(ss, pformat,
                                      PIPE_BIND_SAMPLER_VIEW);
       assert(format != SVGA3D_FORMAT_INVALID);
 
       /* Convert the format to a sampler-friendly format, if needed */
       format = svga_sampler_format(format);
 
       if (texture->target == PIPE_BUFFER) {
-         viewDesc.buffer.firstElement = sv->base.u.buf.first_element;
-         viewDesc.buffer.numElements = (sv->base.u.buf.last_element -
-                                        sv->base.u.buf.first_element + 1);
+         unsigned elem_size = util_format_get_blocksize(sv->base.format);
+
+         viewDesc.buffer.firstElement = sv->base.u.buf.offset / elem_size;
+         viewDesc.buffer.numElements = sv->base.u.buf.size / elem_size;
       }
       else {
          viewDesc.tex.mostDetailedMip = sv->base.u.tex.first_level;
          viewDesc.tex.firstArraySlice = sv->base.u.tex.first_layer;
          viewDesc.tex.mipLevels = (sv->base.u.tex.last_level -
                                    sv->base.u.tex.first_level + 1);
       }
 
       /* arraySize in viewDesc specifies the number of array slices in a
        * texture array. For 3D texture, last_layer in
diff --git a/src/gallium/drivers/trace/tr_dump_state.c 
b/src/gallium/drivers/trace/tr_dump_state.c
index bc129e0..d80037a 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -536,22 +536,22 @@ void trace_dump_sampler_view_template(const struct 
pipe_sampler_view *state,
 
    trace_dump_struct_begin("pipe_sampler_view");
 
    trace_dump_member(format, state, format);
 
    trace_dump_member_begin("u");
    trace_dump_struct_begin(""); /* anonymous */
    if (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, first_level);
       trace_dump_member(uint, &state->u.tex, last_level);
       trace_dump_struct_end(); /* anonymous */
diff --git a/src/gallium/drivers/virgl/virgl_encode.c 
b/src/gallium/drivers/virgl/virgl_encode.c
index 1a1c40b..be72f70 100644
--- a/src/gallium/drivers/virgl/virgl_encode.c
+++ b/src/gallium/drivers/virgl/virgl_encode.c
@@ -15,20 +15,21 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #include <stdint.h>
 
+#include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
 #include "pipe/p_state.h"
 #include "tgsi/tgsi_dump.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "virgl_context.h"
 #include "virgl_encode.h"
 #include "virgl_protocol.h"
 #include "virgl_resource.h"
@@ -555,28 +556,30 @@ int virgl_encode_sampler_state(struct virgl_context *ctx,
       virgl_encoder_write_dword(ctx->cbuf, state->border_color.ui[i]);
    return 0;
 }
 
 
 int virgl_encode_sampler_view(struct virgl_context *ctx,
                              uint32_t handle,
                              struct virgl_resource *res,
                              const struct pipe_sampler_view *state)
 {
+   unsigned elem_size = util_format_get_blocksize(state->format);
+
    uint32_t tmp;
    virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_CREATE_OBJECT, 
VIRGL_OBJECT_SAMPLER_VIEW, VIRGL_OBJ_SAMPLER_VIEW_SIZE));
    virgl_encoder_write_dword(ctx->cbuf, handle);
    virgl_encoder_write_res(ctx, res);
    virgl_encoder_write_dword(ctx->cbuf, state->format);
    if (res->u.b.target == PIPE_BUFFER) {
-      virgl_encoder_write_dword(ctx->cbuf, state->u.buf.first_element);
-      virgl_encoder_write_dword(ctx->cbuf, state->u.buf.last_element);
+      virgl_encoder_write_dword(ctx->cbuf, state->u.buf.offset / elem_size);
+      virgl_encoder_write_dword(ctx->cbuf, (state->u.buf.offset + 
state->u.buf.size) / elem_size - 1);
    } else {
       virgl_encoder_write_dword(ctx->cbuf, state->u.tex.first_layer | 
state->u.tex.last_layer << 16);
       virgl_encoder_write_dword(ctx->cbuf, state->u.tex.first_level | 
state->u.tex.last_level << 8);
    }
    tmp = VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_R(state->swizzle_r) |
       VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_G(state->swizzle_g) |
       VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_B(state->swizzle_b) |
       VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_A(state->swizzle_a);
    virgl_encoder_write_dword(ctx->cbuf, tmp);
    return 0;
diff --git a/src/gallium/include/pipe/p_state.h 
b/src/gallium/include/pipe/p_state.h
index a3ae870..1fd6353 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -421,22 +421,22 @@ struct pipe_sampler_view
    struct pipe_resource *texture; /**< texture into which this is a view  */
    struct pipe_context *context; /**< context this view belongs to */
    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 first_level:8;   /**< first mipmap level to use */
          unsigned last_level:8;    /**< last mipmap level to use */
       } tex;
       struct {
-         unsigned first_element;
-         unsigned last_element;
+         unsigned offset;   /**< offset in bytes */
+         unsigned size;     /**< size of the readable sub-range in bytes */
       } buf;
    } u;
    unsigned swizzle_r:3;         /**< PIPE_SWIZZLE_x for red component */
    unsigned swizzle_g:3;         /**< PIPE_SWIZZLE_x for green component */
    unsigned swizzle_b:3;         /**< PIPE_SWIZZLE_x for blue component */
    unsigned swizzle_a:3;         /**< PIPE_SWIZZLE_x for alpha component */
 };
 
 
 /**
diff --git a/src/mesa/state_tracker/st_atom_texture.c 
b/src/mesa/state_tracker/st_atom_texture.c
index 923cb93..9ee476d 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -272,35 +272,30 @@ st_create_texture_sampler_view_from_stobj(struct 
st_context *st,
 {
    struct pipe_sampler_view templ;
    unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version);
 
    u_sampler_view_default_template(&templ,
                                    stObj->pt,
                                    format);
 
    if (stObj->pt->target == PIPE_BUFFER) {
       unsigned base, size;
-      unsigned f, n;
-      const struct util_format_description *desc
-         = util_format_description(templ.format);
 
       base = stObj->base.BufferOffset;
       if (base >= stObj->pt->width0)
          return NULL;
       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;
-      if (!n)
+      if (!size)
          return NULL;
-      templ.u.buf.first_element = f;
-      templ.u.buf.last_element  = f + (n - 1);
+
+      templ.u.buf.offset = base;
+      templ.u.buf.size = size;
    } else {
       templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
       templ.u.tex.last_level = last_level(stObj);
       assert(templ.u.tex.first_level <= templ.u.tex.last_level);
       templ.u.tex.first_layer = stObj->base.MinLayer;
       templ.u.tex.last_layer = last_layer(stObj);
       assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
       templ.target = gl_target_to_pipe(stObj->base.Target);
    }
 
diff --git a/src/mesa/state_tracker/st_cb_texture.c 
b/src/mesa/state_tracker/st_cb_texture.c
index ab06195..5a2298c 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -1125,22 +1125,23 @@ try_pbo_upload_common(struct gl_context *ctx,
    /* Set up the sampler_view */
    {
       struct pipe_sampler_view templ;
       struct pipe_sampler_view *sampler_view;
       struct pipe_sampler_state sampler = {0};
       const struct pipe_sampler_state *samplers[1] = {&sampler};
 
       memset(&templ, 0, sizeof(templ));
       templ.target = PIPE_BUFFER;
       templ.format = src_format;
-      templ.u.buf.first_element = addr->first_element;
-      templ.u.buf.last_element = addr->last_element;
+      templ.u.buf.offset = addr->first_element * addr->bytes_per_pixel;
+      templ.u.buf.size = (addr->last_element - addr->first_element + 1) *
+                         addr->bytes_per_pixel;
       templ.swizzle_r = PIPE_SWIZZLE_X;
       templ.swizzle_g = PIPE_SWIZZLE_Y;
       templ.swizzle_b = PIPE_SWIZZLE_Z;
       templ.swizzle_a = PIPE_SWIZZLE_W;
 
       sampler_view = pipe->create_sampler_view(pipe, addr->buffer, &templ);
       if (sampler_view == NULL)
          goto fail;
 
       cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to