From: Eric Anholt Date: Tue, 26 Nov 2019 20:02:34 +0000 (-0800) Subject: freedreno: Move a6xx's setup_slices() to a shareable helper function. X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=d9cf3e76bd45e83721f8ab7b9322302741d99668 freedreno: Move a6xx's setup_slices() to a shareable helper function. We pass in all the parameters for setting up the layout, though freedreno still sets a few of them up early (since it uses layout helpers in making some decisions about the layout setup parameters that will be cleaned up once krh's blitter work lands). --- diff --git a/src/freedreno/Makefile.sources b/src/freedreno/Makefile.sources index f6e28520acd..fb0b9f2159f 100644 --- a/src/freedreno/Makefile.sources +++ b/src/freedreno/Makefile.sources @@ -15,6 +15,8 @@ drm_SOURCES := \ drm/msm_ringbuffer.c ir3_SOURCES := \ + fdl/fd6_layout.c \ + fdl/freedreno_layout.c \ ir3/disasm-a3xx.c \ ir3/instr-a3xx.h \ ir3/ir3.c \ diff --git a/src/freedreno/fdl/fd6_layout.c b/src/freedreno/fdl/fd6_layout.c new file mode 100644 index 00000000000..f9499b3a8a6 --- /dev/null +++ b/src/freedreno/fdl/fd6_layout.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2018 Rob Clark + * Copyright © 2018-2019 Google, Inc. + * + * 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: + * Rob Clark + */ + +#include + +#include "freedreno_layout.h" + +/* indexed by cpp, including msaa 2x and 4x: */ +static const struct { + unsigned pitchalign; + unsigned heightalign; +} tile_alignment[] = { + [1] = { 128, 32 }, + [2] = { 64, 32 }, + [3] = { 64, 32 }, + [4] = { 64, 16 }, + [6] = { 64, 16 }, + [8] = { 64, 16 }, + [12] = { 64, 16 }, + [16] = { 64, 16 }, + [24] = { 64, 16 }, + [32] = { 64, 16 }, + [48] = { 64, 16 }, + [64] = { 64, 16 }, + + /* special cases for r16: */ + [0] = { 128, 16 }, +}; + +/* NOTE: good way to test this is: (for example) + * piglit/bin/texelFetch fs sampler3D 100x100x8 + */ +void +fdl6_layout(struct fdl_layout *layout, + enum pipe_format format, uint32_t nr_samples, + uint32_t width0, uint32_t height0, uint32_t depth0, + uint32_t mip_levels, uint32_t array_size, bool is_3d) +{ + assert(nr_samples > 0); + layout->width0 = width0; + layout->height0 = height0; + layout->depth0 = depth0; + + layout->cpp = util_format_get_blocksize(format); + layout->cpp *= nr_samples; + + const struct util_format_description *format_desc = + util_format_description(format); + uint32_t level; + uint32_t depth = depth0; + /* linear dimensions: */ + uint32_t lwidth = width0; + uint32_t lheight = height0; + /* tile_mode dimensions: */ + uint32_t twidth = util_next_power_of_two(lwidth); + uint32_t theight = util_next_power_of_two(lheight); + int ta = layout->cpp; + + /* The z16/r16 formats seem to not play by the normal tiling rules: */ + if ((layout->cpp == 2) && (util_format_get_nr_components(format) == 1)) + ta = 0; + + uint32_t alignment; + if (is_3d) { + layout->layer_first = false; + alignment = 4096; + } else { + layout->layer_first = true; + alignment = 1; + } + /* in layer_first layout, the level (slice) contains just one + * layer (since in fact the layer contains the slices) + */ + uint32_t layers_in_level = layout->layer_first ? 1 : array_size; + + debug_assert(ta < ARRAY_SIZE(tile_alignment)); + debug_assert(tile_alignment[ta].pitchalign); + + for (level = 0; level < mip_levels; level++) { + struct fdl_slice *slice = &layout->slices[level]; + uint32_t tile_mode = fdl_tile_mode(layout, level); + uint32_t width, height; + + /* tiled levels of 3D textures are rounded up to PoT dimensions: */ + if (is_3d && tile_mode) { + width = twidth; + height = theight; + } else { + width = lwidth; + height = lheight; + } + uint32_t aligned_height = height; + uint32_t pitchalign; + + if (tile_mode) { + pitchalign = tile_alignment[ta].pitchalign; + aligned_height = align(aligned_height, + tile_alignment[ta].heightalign); + } else { + pitchalign = 64; + } + + /* The blits used for mem<->gmem work at a granularity of + * 32x32, which can cause faults due to over-fetch on the + * last level. The simple solution is to over-allocate a + * bit the last level to ensure any over-fetch is harmless. + * The pitch is already sufficiently aligned, but height + * may not be: + */ + if (level == mip_levels - 1) + aligned_height = align(aligned_height, 32); + + if (format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC) + slice->pitch = + util_align_npot(width, pitchalign * util_format_get_blockwidth(format)); + else + slice->pitch = align(width, pitchalign); + + slice->offset = layout->size; + uint32_t blocks = util_format_get_nblocks(format, + slice->pitch, aligned_height); + + /* 1d array and 2d array textures must all have the same layer size + * for each miplevel on a6xx. 3d textures can have different layer + * sizes for high levels, but the hw auto-sizer is buggy (or at least + * different than what this code does), so as soon as the layer size + * range gets into range, we stop reducing it. + */ + if (is_3d) { + if (level < 1 || layout->slices[level - 1].size0 > 0xf000) { + slice->size0 = align(blocks * layout->cpp, alignment); + } else { + slice->size0 = layout->slices[level - 1].size0; + } + } else { + slice->size0 = align(blocks * layout->cpp, alignment); + } + + layout->size += slice->size0 * depth * layers_in_level; + + if (false) { + fprintf(stderr, "%s: %ux%ux%u@%u:\t%2u: stride=%4u, size=%6u,%7u, aligned_height=%3u, blocks=%u, offset=0x%x tiling=%d\n", + util_format_name(format), + width, height, depth, layout->cpp, + level, slice->pitch * layout->cpp, + slice->size0, layout->size, aligned_height, blocks, + slice->offset, tile_mode); + } + + depth = u_minify(depth, 1); + lwidth = u_minify(lwidth, 1); + lheight = u_minify(lheight, 1); + twidth = u_minify(twidth, 1); + theight = u_minify(theight, 1); + } + + if (layout->layer_first) { + layout->layer_size = align(layout->size, 4096); + layout->size = layout->layer_size * array_size; + } +} diff --git a/src/freedreno/fdl/freedreno_layout.c b/src/freedreno/fdl/freedreno_layout.c new file mode 100644 index 00000000000..6f604333560 --- /dev/null +++ b/src/freedreno/fdl/freedreno_layout.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Rob Clark + * Copyright © 2018 Google, Inc. + * + * 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: + * Rob Clark + */ + +#include + +#include "freedreno_layout.h" + +void +fdl_layout_buffer(struct fdl_layout *layout, uint32_t size) +{ + layout->width0 = size; + layout->height0 = 1; + layout->depth0 = 1; + layout->cpp = 1; + layout->size = size; +} diff --git a/src/freedreno/fdl/freedreno_layout.h b/src/freedreno/fdl/freedreno_layout.h index 714a6fcf42e..be73a24ccc5 100644 --- a/src/freedreno/fdl/freedreno_layout.h +++ b/src/freedreno/fdl/freedreno_layout.h @@ -24,6 +24,13 @@ #ifndef FREEDRENO_LAYOUT_H_ #define FREEDRENO_LAYOUT_H_ +#include +#include + +#include "util/u_debug.h" +#include "util/u_math.h" +#include "util/format/u_format.h" + /* Shared freedreno mipmap layout helper * * It does *not* attempt to track surface transitions, in particular @@ -102,6 +109,8 @@ struct fdl_layout { uint32_t width0, height0, depth0; + uint32_t size; /* Size of the whole image, in bytes. */ + uint32_t ubwc_size; }; @@ -128,8 +137,8 @@ fdl_ubwc_offset(const struct fdl_layout *layout, unsigned level, unsigned layer) * for multi layer/level images, it will. */ if (layout->ubwc_size) { - debug_assert(level == 0); - debug_assert(layer == 0); + assert(level == 0); + assert(layer == 0); } return layout->ubwc_slices[0].offset; } @@ -158,4 +167,13 @@ fdl_ubwc_enabled(const struct fdl_layout *layout, int level) return layout->ubwc_size && fdl_tile_mode(layout, level); } +void +fdl_layout_buffer(struct fdl_layout *layout, uint32_t size); + +void +fdl6_layout(struct fdl_layout *layout, + enum pipe_format format, uint32_t nr_samples, + uint32_t width0, uint32_t height0, uint32_t depth0, + uint32_t mip_levels, uint32_t array_size, bool is_3d); + #endif /* FREEDRENO_LAYOUT_H_ */ diff --git a/src/freedreno/fdl/meson.build b/src/freedreno/fdl/meson.build new file mode 100644 index 00000000000..429be170a8b --- /dev/null +++ b/src/freedreno/fdl/meson.build @@ -0,0 +1,33 @@ +# Copyright © 2018 Rob Clark + +# 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 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. + +libfreedreno_layout = static_library( + 'freedreno_layout', + [ + 'fd6_layout.c', + 'freedreno_layout.c', + ], + include_directories : [inc_freedreno, inc_common], + c_args : [c_vis_args, no_override_init_args], + cpp_args : [cpp_vis_args], + dependencies : idep_nir_headers, + build_by_default : false, +) + diff --git a/src/freedreno/meson.build b/src/freedreno/meson.build index 5764d4c38ea..1ff2a4fee31 100644 --- a/src/freedreno/meson.build +++ b/src/freedreno/meson.build @@ -21,6 +21,7 @@ inc_freedreno = include_directories(['.', './registers']) subdir('drm') +subdir('fdl') subdir('ir3') subdir('registers') subdir('perfcntrs') diff --git a/src/freedreno/vulkan/meson.build b/src/freedreno/vulkan/meson.build index 45f9602abeb..27f731a98c2 100644 --- a/src/freedreno/vulkan/meson.build +++ b/src/freedreno/vulkan/meson.build @@ -110,6 +110,7 @@ libvulkan_freedreno = shared_library( libvulkan_wsi, libfreedreno_drm, # required by ir3_shader_get_variant, which we don't use libfreedreno_ir3, + libfreedreno_layout, ], dependencies : [ dep_dl, diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c index 4a35dd6db2f..8801982a7a7 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_resource.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_resource.c @@ -30,139 +30,6 @@ #include "a6xx.xml.h" -/* indexed by cpp, including msaa 2x and 4x: */ -static const struct { - unsigned pitchalign; - unsigned heightalign; -} tile_alignment[] = { - [1] = { 128, 32 }, - [2] = { 64, 32 }, - [3] = { 64, 32 }, - [4] = { 64, 16 }, - [6] = { 64, 16 }, - [8] = { 64, 16 }, - [12] = { 64, 16 }, - [16] = { 64, 16 }, - [24] = { 64, 16 }, - [32] = { 64, 16 }, - [48] = { 64, 16 }, - [64] = { 64, 16 }, - - /* special cases for r16: */ - [0] = { 128, 16 }, -}; - -/* NOTE: good way to test this is: (for example) - * piglit/bin/texelFetch fs sampler3D 100x100x8 - */ -static uint32_t -setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format format) -{ - struct pipe_resource *prsc = &rsc->base; - struct fd_screen *screen = fd_screen(prsc->screen); - enum util_format_layout layout = util_format_description(format)->layout; - uint32_t pitchalign = screen->gmem_alignw; - uint32_t level, size = 0; - uint32_t depth = prsc->depth0; - /* linear dimensions: */ - uint32_t lwidth = prsc->width0; - uint32_t lheight = prsc->height0; - /* tile_mode dimensions: */ - uint32_t twidth = util_next_power_of_two(lwidth); - uint32_t theight = util_next_power_of_two(lheight); - /* in layer_first layout, the level (slice) contains just one - * layer (since in fact the layer contains the slices) - */ - uint32_t layers_in_level = rsc->layout.layer_first ? 1 : prsc->array_size; - int ta = rsc->layout.cpp; - - /* The z16/r16 formats seem to not play by the normal tiling rules: */ - if ((rsc->layout.cpp == 2) && (util_format_get_nr_components(format) == 1)) - ta = 0; - - debug_assert(ta < ARRAY_SIZE(tile_alignment)); - debug_assert(tile_alignment[ta].pitchalign); - - for (level = 0; level <= prsc->last_level; level++) { - struct fdl_slice *slice = fd_resource_slice(rsc, level); - uint32_t tile_mode = fd_resource_tile_mode(prsc, level); - uint32_t width, height; - - /* tiled levels of 3D textures are rounded up to PoT dimensions: */ - if ((prsc->target == PIPE_TEXTURE_3D) && tile_mode) { - width = twidth; - height = theight; - } else { - width = lwidth; - height = lheight; - } - uint32_t aligned_height = height; - uint32_t blocks; - - if (tile_mode) { - pitchalign = tile_alignment[ta].pitchalign; - aligned_height = align(aligned_height, - tile_alignment[ta].heightalign); - } else { - pitchalign = 64; - } - - /* The blits used for mem<->gmem work at a granularity of - * 32x32, which can cause faults due to over-fetch on the - * last level. The simple solution is to over-allocate a - * bit the last level to ensure any over-fetch is harmless. - * The pitch is already sufficiently aligned, but height - * may not be: - */ - if ((level == prsc->last_level) && (prsc->target != PIPE_BUFFER)) - aligned_height = align(aligned_height, 32); - - if (layout == UTIL_FORMAT_LAYOUT_ASTC) - slice->pitch = - util_align_npot(width, pitchalign * util_format_get_blockwidth(format)); - else - slice->pitch = align(width, pitchalign); - - slice->offset = size; - blocks = util_format_get_nblocks(format, slice->pitch, aligned_height); - - /* 1d array and 2d array textures must all have the same layer size - * for each miplevel on a6xx. 3d textures can have different layer - * sizes for high levels, but the hw auto-sizer is buggy (or at least - * different than what this code does), so as soon as the layer size - * range gets into range, we stop reducing it. - */ - if (prsc->target == PIPE_TEXTURE_3D) { - if (level < 1 || fd_resource_slice(rsc, level - 1)->size0 > 0xf000) { - slice->size0 = align(blocks * rsc->layout.cpp, alignment); - } else { - slice->size0 = fd_resource_slice(rsc, level - 1)->size0; - } - } else { - slice->size0 = align(blocks * rsc->layout.cpp, alignment); - } - - size += slice->size0 * depth * layers_in_level; - -#if 0 - fprintf(stderr, "%s: %ux%ux%u@%u:\t%2u: stride=%4u, size=%6u,%7u, aligned_height=%3u, blocks=%u, offset=0x%x tiling=%d\n", - util_format_name(prsc->format), - width, height, depth, rsc->layout.cpp, - level, slice->pitch * rsc->layout.cpp, - slice->size0, size, aligned_height, blocks, - slice->offset, fd_resource_tile_mode(prsc, level)); -#endif - - depth = u_minify(depth, 1); - lwidth = u_minify(lwidth, 1); - lheight = u_minify(lheight, 1); - twidth = u_minify(twidth, 1); - theight = u_minify(theight, 1); - } - - return size; -} - /* A subset of the valid tiled formats can be compressed. We do * already require tiled in order to be compressed, but just because * it can be tiled doesn't mean it can be compressed. @@ -325,21 +192,19 @@ setup_lrz(struct fd_resource *rsc) uint32_t fd6_setup_slices(struct fd_resource *rsc) { - uint32_t alignment; + struct pipe_resource *prsc = &rsc->base; if (!(fd_mesa_debug & FD_DBG_NOLRZ) && has_depth(rsc->base.format)) setup_lrz(rsc); - switch (rsc->base.target) { - case PIPE_TEXTURE_3D: - rsc->layout.layer_first = false; - alignment = 4096; - break; - default: - rsc->layout.layer_first = true; - alignment = 1; - break; - } + fdl6_layout(&rsc->layout, prsc->format, fd_resource_nr_samples(prsc), + prsc->width0, prsc->height0, prsc->depth0, + prsc->last_level + 1, prsc->array_size, + prsc->target == PIPE_TEXTURE_3D); - return setup_slices(rsc, alignment, rsc->base.format); + /* The caller does this bit of layout setup again. */ + if (rsc->layout.layer_first) + return rsc->layout.size / prsc->array_size; + else + return rsc->layout.size; } diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 5826e16c154..10e9196886f 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -991,7 +991,13 @@ fd_resource_create_with_modifiers(struct pipe_screen *pscreen, rsc->internal_format = format; - size = screen->setup_slices(rsc); + if (prsc->target == PIPE_BUFFER) { + assert(prsc->format == PIPE_FORMAT_R8_UNORM); + size = prsc->width0; + fdl_layout_buffer(&rsc->layout, size); + } else { + size = screen->setup_slices(rsc); + } if (allow_ubwc && screen->fill_ubwc_buffer_sizes && rsc->layout.tile_mode) size += screen->fill_ubwc_buffer_sizes(rsc); diff --git a/src/gallium/drivers/freedreno/meson.build b/src/gallium/drivers/freedreno/meson.build index 09cf125c61d..7125ecd274f 100644 --- a/src/gallium/drivers/freedreno/meson.build +++ b/src/gallium/drivers/freedreno/meson.build @@ -243,6 +243,7 @@ driver_freedreno = declare_dependency( libfreedreno, libfreedreno_drm, libfreedreno_ir3, + libfreedreno_layout, libfreedreno_perfcntrs ], dependencies : idep_nir, @@ -260,6 +261,7 @@ ir3_compiler = executable( libfreedreno, libfreedreno_drm, libfreedreno_ir3, + libfreedreno_layout, libgallium, libglsl_standalone, ],