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