From 3a273a4abcd3032b01960f10243463b69bf31552 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Tue, 13 Nov 2018 11:40:03 -0500 Subject: [PATCH] freedreno: a2xx texture update Adds all missing texture related logic. For everything to work it also needs changes to ir2/fd2_program, which are part of the ir2 update patch. Note: it needs rnndb update Signed-off-by: Jonathan Marek [remove stray patch] Signed-off-by: Rob Clark --- .../drivers/freedreno/Makefile.sources | 2 + src/gallium/drivers/freedreno/a2xx/fd2_emit.c | 15 +++- src/gallium/drivers/freedreno/a2xx/fd2_gmem.c | 26 +++++-- .../drivers/freedreno/a2xx/fd2_resource.c | 73 +++++++++++++++++++ .../drivers/freedreno/a2xx/fd2_resource.h | 34 +++++++++ .../drivers/freedreno/a2xx/fd2_screen.c | 6 +- .../drivers/freedreno/a2xx/fd2_texture.c | 67 +++++++++++++++-- .../drivers/freedreno/a2xx/fd2_texture.h | 7 +- src/gallium/drivers/freedreno/meson.build | 2 + 9 files changed, 212 insertions(+), 20 deletions(-) create mode 100644 src/gallium/drivers/freedreno/a2xx/fd2_resource.c create mode 100644 src/gallium/drivers/freedreno/a2xx/fd2_resource.h diff --git a/src/gallium/drivers/freedreno/Makefile.sources b/src/gallium/drivers/freedreno/Makefile.sources index 039a8ca7af7..32574a37b83 100644 --- a/src/gallium/drivers/freedreno/Makefile.sources +++ b/src/gallium/drivers/freedreno/Makefile.sources @@ -59,6 +59,8 @@ a2xx_SOURCES := \ a2xx/fd2_program.h \ a2xx/fd2_rasterizer.c \ a2xx/fd2_rasterizer.h \ + a2xx/fd2_resource.c \ + a2xx/fd2_resource.h \ a2xx/fd2_screen.c \ a2xx/fd2_screen.h \ a2xx/fd2_texture.c \ diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_emit.c b/src/gallium/drivers/freedreno/a2xx/fd2_emit.c index 50e2fe13ebb..60bc9fad4c7 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_emit.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_emit.c @@ -118,6 +118,7 @@ emit_texture(struct fd_ringbuffer *ring, struct fd_context *ctx, static const struct fd2_pipe_sampler_view dummy_view = {}; const struct fd2_sampler_stateobj *sampler; const struct fd2_pipe_sampler_view *view; + struct fd_resource *rsc; if (emitted & (1 << const_idx)) return 0; @@ -129,19 +130,25 @@ emit_texture(struct fd_ringbuffer *ring, struct fd_context *ctx, fd2_pipe_sampler_view(tex->textures[samp_id]) : &dummy_view; + rsc = view->base.texture ? fd_resource(view->base.texture) : NULL; + OUT_PKT3(ring, CP_SET_CONSTANT, 7); OUT_RING(ring, 0x00010000 + (0x6 * const_idx)); OUT_RING(ring, sampler->tex0 | view->tex0); - if (view->base.texture) - OUT_RELOC(ring, fd_resource(view->base.texture)->bo, 0, view->fmt, 0); + if (rsc) + OUT_RELOC(ring, rsc->bo, 0, view->tex1, 0); else OUT_RING(ring, 0); OUT_RING(ring, view->tex2); OUT_RING(ring, sampler->tex3 | view->tex3); - OUT_RING(ring, sampler->tex4); - OUT_RING(ring, sampler->tex5); + OUT_RING(ring, sampler->tex4 | view->tex4); + + if (rsc && rsc->base.last_level) + OUT_RELOC(ring, rsc->bo, fd_resource_offset(rsc, 1, 0), view->tex5, 0); + else + OUT_RING(ring, view->tex5); return (1 << const_idx); } diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c b/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c index 5770d6248ee..e98ae7334ac 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c @@ -66,6 +66,13 @@ emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base, struct fd_ringbuffer *ring = batch->gmem; struct fd_resource *rsc = fd_resource(psurf->texture); uint32_t swap = fmt2swap(psurf->format); + struct fd_resource_slice *slice = + fd_resource_slice(rsc, psurf->u.tex.level); + uint32_t offset = + fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer); + + assert((slice->pitch & 31) == 0); + assert((offset & 0xfff) == 0); if (!rsc->valid) return; @@ -79,8 +86,8 @@ emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base, OUT_PKT3(ring, CP_SET_CONSTANT, 5); OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL)); OUT_RING(ring, 0x00000000); /* RB_COPY_CONTROL */ - OUT_RELOCW(ring, rsc->bo, 0, 0, 0); /* RB_COPY_DEST_BASE */ - OUT_RING(ring, rsc->slices[0].pitch >> 5); /* RB_COPY_DEST_PITCH */ + OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* RB_COPY_DEST_BASE */ + OUT_RING(ring, slice->pitch >> 5); /* RB_COPY_DEST_PITCH */ OUT_RING(ring, /* RB_COPY_DEST_INFO */ A2XX_RB_COPY_DEST_INFO_FORMAT(fd2_pipe2color(psurf->format)) | A2XX_RB_COPY_DEST_INFO_LINEAR | @@ -189,6 +196,10 @@ emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base, { struct fd_ringbuffer *ring = batch->gmem; struct fd_resource *rsc = fd_resource(psurf->texture); + struct fd_resource_slice *slice = + fd_resource_slice(rsc, psurf->u.tex.level); + uint32_t offset = + fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer); uint32_t swiz; OUT_PKT3(ring, CP_SET_CONSTANT, 2); @@ -206,17 +217,18 @@ emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base, OUT_RING(ring, A2XX_SQ_TEX_0_CLAMP_X(SQ_TEX_WRAP) | A2XX_SQ_TEX_0_CLAMP_Y(SQ_TEX_WRAP) | A2XX_SQ_TEX_0_CLAMP_Z(SQ_TEX_WRAP) | - A2XX_SQ_TEX_0_PITCH(rsc->slices[0].pitch)); - OUT_RELOC(ring, rsc->bo, 0, - fd2_pipe2surface(psurf->format) | 0x800, 0); + A2XX_SQ_TEX_0_PITCH(slice->pitch)); + OUT_RELOC(ring, rsc->bo, offset, + fd2_pipe2surface(psurf->format) | + A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL), 0); OUT_RING(ring, A2XX_SQ_TEX_2_WIDTH(psurf->width - 1) | A2XX_SQ_TEX_2_HEIGHT(psurf->height - 1)); - OUT_RING(ring, 0x01000000 | // XXX + OUT_RING(ring, A2XX_SQ_TEX_3_MIP_FILTER(SQ_TEX_FILTER_BASEMAP) | swiz | A2XX_SQ_TEX_3_XY_MAG_FILTER(SQ_TEX_FILTER_POINT) | A2XX_SQ_TEX_3_XY_MIN_FILTER(SQ_TEX_FILTER_POINT)); OUT_RING(ring, 0x00000000); - OUT_RING(ring, 0x00000200); + OUT_RING(ring, A2XX_SQ_TEX_5_DIMENSION(SQ_TEX_DIMENSION_2D)); if (!is_a20x(batch->ctx->screen)) { OUT_PKT3(ring, CP_SET_CONSTANT, 3); diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_resource.c b/src/gallium/drivers/freedreno/a2xx/fd2_resource.c new file mode 100644 index 00000000000..1bd1f103ccd --- /dev/null +++ b/src/gallium/drivers/freedreno/a2xx/fd2_resource.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 Jonathan Marek + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Jonathan Marek + */ + +#include "fd2_resource.h" + +uint32_t +fd2_setup_slices(struct fd_resource *rsc) +{ + struct pipe_resource *prsc = &rsc->base; + enum pipe_format format = rsc->base.format; + uint32_t level, size = 0; + uint32_t width = prsc->width0; + uint32_t height = prsc->height0; + uint32_t depth = prsc->depth0; + + for (level = 0; level <= prsc->last_level; level++) { + struct fd_resource_slice *slice = fd_resource_slice(rsc, level); + uint32_t blocks; + + /* 32 * 32 block alignment */ + switch (prsc->target) { + default: assert(0); + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_2D_ARRAY: + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_CUBE: + height = align(height, 32 * util_format_get_blockheight(format)); + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_1D_ARRAY: + width = align(width, 32 * util_format_get_blockwidth(format)); + case PIPE_BUFFER: + break; + } + + slice->pitch = width; + slice->offset = size; + + blocks = util_format_get_nblocks(format, width, height); + + /* 4k aligned size */ + slice->size0 = align(blocks * rsc->cpp, 4096); + + size += slice->size0 * depth * prsc->array_size; + + width = u_minify(width, 1); + height = u_minify(height, 1); + depth = u_minify(depth, 1); + } + return size; +} diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_resource.h b/src/gallium/drivers/freedreno/a2xx/fd2_resource.h new file mode 100644 index 00000000000..7a9d356bf44 --- /dev/null +++ b/src/gallium/drivers/freedreno/a2xx/fd2_resource.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Jonathan Marek + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Jonathan Marek + */ + +#ifndef FD2_RESOURCE_H_ +#define FD2_RESOURCE_H_ + +#include "freedreno_resource.h" + +uint32_t fd2_setup_slices(struct fd_resource *rsc); + +#endif /* FD2_RESOURCE_H_ */ diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_screen.c b/src/gallium/drivers/freedreno/a2xx/fd2_screen.c index e49ff1cb5ce..3b44147cb3d 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_screen.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_screen.c @@ -30,6 +30,7 @@ #include "fd2_screen.h" #include "fd2_context.h" #include "fd2_util.h" +#include "fd2_resource.h" static boolean fd2_screen_is_format_supported(struct pipe_screen *pscreen, @@ -107,7 +108,10 @@ fd2_screen_is_format_supported(struct pipe_screen *pscreen, void fd2_screen_init(struct pipe_screen *pscreen) { - fd_screen(pscreen)->max_rts = 1; + struct fd_screen *screen = fd_screen(pscreen); + + screen->max_rts = 1; pscreen->context_create = fd2_context_create; pscreen->is_format_supported = fd2_screen_is_format_supported; + screen->setup_slices = fd2_setup_slices; } diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_texture.c b/src/gallium/drivers/freedreno/a2xx/fd2_texture.c index 76cabc545da..16bdf6ce9a5 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_texture.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_texture.c @@ -72,6 +72,22 @@ tex_filter(unsigned filter) } } +static enum sq_tex_filter +mip_filter(unsigned filter) +{ + switch (filter) { + case PIPE_TEX_MIPFILTER_NONE: + return SQ_TEX_FILTER_BASEMAP; + case PIPE_TEX_MIPFILTER_NEAREST: + return SQ_TEX_FILTER_POINT; + case PIPE_TEX_MIPFILTER_LINEAR: + return SQ_TEX_FILTER_BILINEAR; + default: + DBG("invalid filter: %u", filter); + return 0; + } +} + static void * fd2_sampler_state_create(struct pipe_context *pctx, const struct pipe_sampler_state *cso) @@ -83,6 +99,11 @@ fd2_sampler_state_create(struct pipe_context *pctx, so->base = *cso; + /* TODO + * cso->max_anisotropy + * cso->normalized_coords (dealt with by shader for rect textures?) + */ + /* SQ_TEX0_PITCH() must be OR'd in later when we know the bound texture: */ so->tex0 = A2XX_SQ_TEX_0_CLAMP_X(tex_clamp(cso->wrap_s)) | @@ -91,10 +112,12 @@ fd2_sampler_state_create(struct pipe_context *pctx, so->tex3 = A2XX_SQ_TEX_3_XY_MAG_FILTER(tex_filter(cso->mag_img_filter)) | - A2XX_SQ_TEX_3_XY_MIN_FILTER(tex_filter(cso->min_img_filter)); + A2XX_SQ_TEX_3_XY_MIN_FILTER(tex_filter(cso->min_img_filter)) | + A2XX_SQ_TEX_3_MIP_FILTER(mip_filter(cso->min_mip_filter)); - so->tex4 = 0x00000000; /* ??? */ - so->tex5 = 0x00000200; /* ??? */ + so->tex4 = 0; + if (cso->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) + so->tex4 = A2XX_SQ_TEX_4_LOD_BIAS(cso->lod_bias); return so; } @@ -121,6 +144,26 @@ fd2_sampler_states_bind(struct pipe_context *pctx, fd_sampler_states_bind(pctx, shader, start, nr, hwcso); } +static enum sq_tex_dimension +tex_dimension(unsigned target) +{ + switch (target) { + default: + assert(0); + case PIPE_TEXTURE_1D: + assert(0); /* TODO */ + return SQ_TEX_DIMENSION_1D; + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D: + return SQ_TEX_DIMENSION_2D; + case PIPE_TEXTURE_3D: + assert(0); /* TODO */ + return SQ_TEX_DIMENSION_3D; + case PIPE_TEXTURE_CUBE: + return SQ_TEX_DIMENSION_CUBE; + } +} + static struct pipe_sampler_view * fd2_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, const struct pipe_sampler_view *cso) @@ -137,15 +180,22 @@ fd2_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, so->base.reference.count = 1; so->base.context = pctx; - so->fmt = fd2_pipe2surface(cso->format); - so->tex0 = A2XX_SQ_TEX_0_PITCH(rsc->slices[0].pitch); + so->tex1 = + A2XX_SQ_TEX_1_FORMAT(fd2_pipe2surface(cso->format)) | + A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL); so->tex2 = A2XX_SQ_TEX_2_HEIGHT(prsc->height0 - 1) | A2XX_SQ_TEX_2_WIDTH(prsc->width0 - 1); so->tex3 = fd2_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g, cso->swizzle_b, cso->swizzle_a); + so->tex4 = + A2XX_SQ_TEX_4_MIP_MIN_LEVEL(fd_sampler_first_level(cso)) | + A2XX_SQ_TEX_4_MIP_MAX_LEVEL(fd_sampler_last_level(cso)); + + so->tex5 = A2XX_SQ_TEX_5_DIMENSION(tex_dimension(prsc->target)); + return &so->base; } @@ -188,6 +238,13 @@ fd2_get_const_idx(struct fd_context *ctx, struct fd_texture_stateobj *tex, return samp_id + ctx->tex[PIPE_SHADER_FRAGMENT].num_samplers; } +/* for reasons unknown, it appears ETC1 cubemap needs swapped xy coordinates */ +bool fd2_texture_swap_xy(struct fd_texture_stateobj *tex, unsigned samp_id) +{ + return tex->textures[samp_id]->format == PIPE_FORMAT_ETC1_RGB8 && + tex->textures[samp_id]->texture->target == PIPE_TEXTURE_CUBE; +} + void fd2_texture_init(struct pipe_context *pctx) { diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_texture.h b/src/gallium/drivers/freedreno/a2xx/fd2_texture.h index 9943e0d3338..045be08ece1 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_texture.h +++ b/src/gallium/drivers/freedreno/a2xx/fd2_texture.h @@ -37,7 +37,7 @@ struct fd2_sampler_stateobj { struct pipe_sampler_state base; - uint32_t tex0, tex3, tex4, tex5; + uint32_t tex0, tex3, tex4; }; static inline struct fd2_sampler_stateobj * @@ -48,8 +48,7 @@ fd2_sampler_stateobj(struct pipe_sampler_state *samp) struct fd2_pipe_sampler_view { struct pipe_sampler_view base; - enum a2xx_sq_surfaceformat fmt; - uint32_t tex0, tex2, tex3; + uint32_t tex0, tex1, tex2, tex3, tex4, tex5; }; static inline struct fd2_pipe_sampler_view * @@ -61,6 +60,8 @@ fd2_pipe_sampler_view(struct pipe_sampler_view *pview) unsigned fd2_get_const_idx(struct fd_context *ctx, struct fd_texture_stateobj *tex, unsigned samp_id); +bool fd2_texture_swap_xy(struct fd_texture_stateobj *tex, unsigned samp_id); + void fd2_texture_init(struct pipe_context *pctx); #endif /* FD2_TEXTURE_H_ */ diff --git a/src/gallium/drivers/freedreno/meson.build b/src/gallium/drivers/freedreno/meson.build index f996126e386..366b1468bef 100644 --- a/src/gallium/drivers/freedreno/meson.build +++ b/src/gallium/drivers/freedreno/meson.build @@ -77,6 +77,8 @@ files_libfreedreno = files( 'a2xx/fd2_program.h', 'a2xx/fd2_rasterizer.c', 'a2xx/fd2_rasterizer.h', + 'a2xx/fd2_resource.c', + 'a2xx/fd2_resource.h', 'a2xx/fd2_screen.c', 'a2xx/fd2_screen.h', 'a2xx/fd2_texture.c', -- 2.30.2