From: Rob Clark Date: Tue, 11 Aug 2015 20:47:16 +0000 (-0400) Subject: freedreno/a3xx+a4xx: add texture buffer object support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=500025a23784877c8a61d8b3c7a8eab6fddf242a;p=mesa.git freedreno/a3xx+a4xx: add texture buffer object support Basic texture buffer support. Should be straightforward to add first/ last_element support. And with a bit of work in ir3 emulate larger texture buffer sizes. But this seems to be enough for stk gl31 render paths. Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index 49b3d97cce8..752e7f88cb9 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -251,14 +251,15 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0)); 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); - unsigned start = view->base.u.tex.first_level; - unsigned end = view->base.u.tex.last_level; + 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 = @@ -341,6 +342,7 @@ fd3_emit_gmem_restore_tex(struct fd_ringbuffer *ring, format = fd3_gmem_restore_format(rsc->base.b.format); } + /* note: PIPE_BUFFER disallowed for surfaces */ unsigned lvl = psurf[i]->u.tex.level; struct fd_resource_slice *slice = fd_resource_slice(rsc, lvl); diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c index a278bf5c603..c30658d0e7b 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c @@ -210,8 +210,8 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, { struct fd3_pipe_sampler_view *so = CALLOC_STRUCT(fd3_pipe_sampler_view); struct fd_resource *rsc = fd_resource(prsc); - unsigned lvl = cso->u.tex.first_level; - unsigned miplevels = cso->u.tex.last_level - lvl; + unsigned lvl = fd_sampler_first_level(cso); + unsigned miplevels = fd_sampler_last_level(cso) - lvl; uint32_t sz2 = 0; if (!so) diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index c3226d5121f..b75be29e523 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -172,7 +172,7 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, const struct fd4_pipe_sampler_view *view = tex->textures[i] ? fd4_pipe_sampler_view(tex->textures[i]) : &dummy_view; - unsigned start = view->base.u.tex.first_level; + unsigned start = fd_sampler_first_level(&view->base); OUT_RING(ring, view->texconst0); OUT_RING(ring, view->texconst1); @@ -235,6 +235,7 @@ fd4_emit_gmem_restore_tex(struct fd_ringbuffer *ring, unsigned nr_bufs, for (i = 0; i < nr_bufs; i++) { if (bufs[i]) { struct fd_resource *rsc = fd_resource(bufs[i]->texture); + /* note: PIPE_BUFFER disallowed for surfaces */ unsigned lvl = bufs[i]->u.tex.level; struct fd_resource_slice *slice = fd_resource_slice(rsc, lvl); uint32_t offset = fd_resource_offset(rsc, lvl, bufs[i]->u.tex.first_layer); diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c index 6ba25d0816d..d2bc5fee6c0 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c @@ -150,8 +150,8 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, { struct fd4_pipe_sampler_view *so = CALLOC_STRUCT(fd4_pipe_sampler_view); struct fd_resource *rsc = fd_resource(prsc); - unsigned lvl = cso->u.tex.first_level; - unsigned miplevels = cso->u.tex.last_level - lvl; + unsigned lvl = fd_sampler_first_level(cso); + unsigned miplevels = fd_sampler_last_level(cso) - lvl; if (!so) return NULL; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 26802b0188a..3aeed57b043 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -164,9 +164,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_CUBE_MAP_ARRAY: - case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: - case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: - case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: case PIPE_CAP_START_INSTANCE: case PIPE_CAP_COMPUTE: @@ -178,8 +175,21 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: + case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: return is_a3xx(screen) || is_a4xx(screen); + case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: + /* ignoring first/last_element.. but I guess that should be + * easy to add.. + */ + return 0; + case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: + /* I think 32k on a4xx.. and we could possibly emulate more + * by pretending 2d/rect textures and splitting high bits + * of index into 2nd dimension.. + */ + return 16383; + case PIPE_CAP_DEPTH_CLIP_DISABLE: return is_a3xx(screen); diff --git a/src/gallium/drivers/freedreno/freedreno_surface.c b/src/gallium/drivers/freedreno/freedreno_surface.c index 250fe4bc0f5..70c44eb79c3 100644 --- a/src/gallium/drivers/freedreno/freedreno_surface.c +++ b/src/gallium/drivers/freedreno/freedreno_surface.c @@ -41,7 +41,8 @@ fd_create_surface(struct pipe_context *pctx, // struct fd_resource* tex = fd_resource(ptex); struct fd_surface* surface = CALLOC_STRUCT(fd_surface); - assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + debug_assert(ptex->target != PIPE_BUFFER); + debug_assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); if (surface) { struct pipe_surface *psurf = &surface->base; diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h index d6a08b5fa13..7129a1bddd1 100644 --- a/src/gallium/drivers/freedreno/freedreno_util.h +++ b/src/gallium/drivers/freedreno/freedreno_util.h @@ -140,6 +140,22 @@ fd_surface_half_precision(const struct pipe_surface *psurf) return true; } +static inline unsigned +fd_sampler_first_level(const struct pipe_sampler_view *view) +{ + if (view->target == PIPE_BUFFER) + return 0; + return view->u.tex.first_level; +} + +static inline unsigned +fd_sampler_last_level(const struct pipe_sampler_view *view) +{ + if (view->target == PIPE_BUFFER) + return 0; + return view->u.tex.last_level; +} + static inline bool fd_half_precision(struct pipe_framebuffer_state *pfb) {