aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/freedreno/Makefile.sources2
-rw-r--r--src/freedreno/fdl/fd6_layout.c185
-rw-r--r--src/freedreno/fdl/freedreno_layout.c40
-rw-r--r--src/freedreno/fdl/freedreno_layout.h22
-rw-r--r--src/freedreno/fdl/meson.build33
-rw-r--r--src/freedreno/meson.build1
-rw-r--r--src/freedreno/vulkan/meson.build1
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_resource.c155
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c8
-rw-r--r--src/gallium/drivers/freedreno/meson.build2
10 files changed, 301 insertions, 148 deletions
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 <[email protected]>
+ * 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 <[email protected]>
+ */
+
+#include <stdio.h>
+
+#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 <[email protected]>
+ * 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 <[email protected]>
+ */
+
+#include <stdio.h>
+
+#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 <stdbool.h>
+#include <stdint.h>
+
+#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,
],