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