#include "freedreno_layout.h"
-/* indexed by cpp: */
-static const struct {
- unsigned pitchalign;
- unsigned heightalign;
-} tile_alignment[] = {
- [1] = { 128, 32 },
- [2] = { 128, 16 },
- [3] = { 128, 16 },
- [4] = { 64, 16 },
- [8] = { 64, 16 },
- [12] = { 64, 16 },
- [16] = { 64, 16 },
-};
-
void
fdl5_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)
{
- const struct util_format_description *format_desc =
- util_format_description(format);
-
assert(nr_samples > 0);
layout->width0 = width0;
layout->height0 = height0;
layout->nr_samples = nr_samples;
layout->layer_first = !is_3d;
- uint32_t pitchalign;
- uint32_t heightalign;
- uint32_t width = width0;
- uint32_t height = height0;
- uint32_t depth = depth0;
+ uint32_t heightalign = layout->cpp == 1 ? 32 : 16;
/* 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;
- heightalign = tile_alignment[layout->cpp].heightalign;
+ /* use 128 pixel alignment for cpp=1 and cpp=2 */
+ if (layout->cpp < 4 && layout->tile_mode)
+ fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 7);
+ else
+ fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 6);
for (uint32_t level = 0; level < mip_levels; level++) {
struct fdl_slice *slice = &layout->slices[level];
uint32_t tile_mode = fdl_tile_mode(layout, level);
- uint32_t aligned_height = height;
- uint32_t blocks;
+ uint32_t pitch = fdl_pitch(layout, level);
+ uint32_t nblocksy = util_format_get_nblocksy(format, u_minify(height0, level));
if (tile_mode) {
- pitchalign = tile_alignment[layout->cpp].pitchalign;
- aligned_height = align(aligned_height, heightalign);
+ nblocksy = align(nblocksy, 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
* may not be:
*/
if (level == mip_levels - 1)
- aligned_height = align(aligned_height, 32);
+ nblocksy = align(nblocksy, 32);
}
- unsigned pitch_pixels;
- if (format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC)
- pitch_pixels =
- util_align_npot(width, pitchalign * util_format_get_blockwidth(format));
- else
- pitch_pixels = align(width, pitchalign);
-
slice->offset = layout->size;
- blocks = util_format_get_nblocks(format, pitch_pixels, aligned_height);
- slice->pitch = util_format_get_nblocksx(format, pitch_pixels) *
- layout->cpp;
const int alignment = is_3d ? 4096 : 1;
if (is_3d && (
level == 1 ||
(level > 1 && layout->slices[level - 1].size0 > 0xf000)))
- slice->size0 = align(blocks * layout->cpp, alignment);
+ slice->size0 = align(nblocksy * pitch, alignment);
else if (level == 0 || layout->layer_first || alignment == 1)
- slice->size0 = align(blocks * layout->cpp, alignment);
+ slice->size0 = align(nblocksy * pitch, alignment);
else
slice->size0 = layout->slices[level - 1].size0;
- layout->size += slice->size0 * depth * layers_in_level;
-
- width = u_minify(width, 1);
- height = u_minify(height, 1);
- depth = u_minify(depth, 1);
+ layout->size += slice->size0 * u_minify(depth0, level) * layers_in_level;
}
}
#include "freedreno_layout.h"
-#define RGB_TILE_WIDTH_ALIGNMENT 64
-#define RGB_TILE_HEIGHT_ALIGNMENT 16
-#define UBWC_PLANE_SIZE_ALIGNMENT 4096
-
static bool
is_r8g8(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,
- struct fdl_slice *plane_layout)
+ struct fdl_explicit_layout *explicit_layout)
{
- uint32_t offset, pitch0;
- uint32_t pitchalign, heightalign;
+ uint32_t offset = 0, heightalign;
uint32_t ubwc_blockwidth, ubwc_blockheight;
assert(nr_samples > 0);
/* when possible, use a bit more alignment than necessary
* presumably this is better for performance?
*/
- if (!plane_layout)
+ if (!explicit_layout)
layout->pitchalign = fdl_cpp_shift(layout);
/* not used, avoid "may be used uninitialized" warning */
heightalign = 1;
}
- pitchalign = 64 << layout->pitchalign;
+ fdl_set_pitchalign(layout, layout->pitchalign + 6);
- if (plane_layout) {
- offset = plane_layout->offset;
- pitch0 = plane_layout->pitch;
- if (align(pitch0, pitchalign) != pitch0)
+ if (explicit_layout) {
+ offset = explicit_layout->offset;
+ layout->pitch0 = explicit_layout->pitch;
+ if (align(layout->pitch0, 1 << layout->pitchalign) != layout->pitch0)
return false;
- } else {
- uint32_t nblocksx = util_format_get_nblocksx(format, width0);
- offset = 0;
- pitch0 = util_align_npot(nblocksx * layout->cpp, pitchalign);
}
uint32_t ubwc_width0 = width0;
ubwc_height0 = util_next_power_of_two(height0);
ubwc_tile_height_alignment = 64;
}
- ubwc_width0 = align(DIV_ROUND_UP(ubwc_width0, ubwc_blockwidth),
- RGB_TILE_WIDTH_ALIGNMENT);
+ layout->ubwc_width0 = align(DIV_ROUND_UP(ubwc_width0, ubwc_blockwidth),
+ RGB_TILE_WIDTH_ALIGNMENT);
ubwc_height0 = align(DIV_ROUND_UP(ubwc_height0, ubwc_blockheight),
ubwc_tile_height_alignment);
struct fdl_slice *slice = &layout->slices[level];
struct fdl_slice *ubwc_slice = &layout->ubwc_slices[level];
uint32_t tile_mode = fdl_tile_mode(layout, level);
+ uint32_t pitch = fdl_pitch(layout, level);
uint32_t height;
/* tiled levels of 3D textures are rounded up to PoT dimensions: */
height = align(nblocksy, 4);
slice->offset = offset + layout->size;
- slice->pitch = align(u_minify(pitch0, level), pitchalign);
/* 1d array and 2d array textures must all have the same layer size
* for each miplevel on a6xx. 3d textures can have different layer
*/
if (is_3d) {
if (level < 1 || layout->slices[level - 1].size0 > 0xf000) {
- slice->size0 = align(nblocksy * slice->pitch, 4096);
+ slice->size0 = align(nblocksy * pitch, 4096);
} else {
slice->size0 = layout->slices[level - 1].size0;
}
} else {
- slice->size0 = nblocksy * slice->pitch;
+ slice->size0 = nblocksy * pitch;
}
layout->size += slice->size0 * depth * layers_in_level;
/* with UBWC every level is aligned to 4K */
layout->size = align(layout->size, 4096);
- uint32_t meta_pitch = align(u_minify(ubwc_width0, level),
- RGB_TILE_WIDTH_ALIGNMENT);
+ uint32_t meta_pitch = fdl_ubwc_pitch(layout, level);
uint32_t meta_height = align(u_minify(ubwc_height0, level),
ubwc_tile_height_alignment);
ubwc_slice->size0 = align(meta_pitch * meta_height, UBWC_PLANE_SIZE_ALIGNMENT);
- ubwc_slice->pitch = meta_pitch;
ubwc_slice->offset = offset + layout->ubwc_layer_size;
layout->ubwc_layer_size += ubwc_slice->size0;
}
testcase->layout.slices[l].offset);
ok = false;
}
- if (layout.slices[l].pitch != testcase->layout.slices[l].pitch) {
+ if (fdl_pitch(&layout, l) != testcase->layout.slices[l].pitch) {
fprintf(stderr, "%s %dx%dx%d@%dx lvl%d: pitch %d != %d\n",
util_format_short_name(testcase->format),
layout.width0, layout.height0, layout.depth0,
layout.nr_samples, l,
- layout.slices[l].pitch,
+ fdl_pitch(&layout, l),
testcase->layout.slices[l].pitch);
ok = false;
}
testcase->layout.ubwc_slices[l].offset);
ok = false;
}
- if (layout.ubwc_slices[l].pitch != testcase->layout.ubwc_slices[l].pitch) {
+ if (fdl_ubwc_pitch(&layout, l) != testcase->layout.ubwc_slices[l].pitch) {
fprintf(stderr, "%s %dx%dx%d@%dx lvl%d: UBWC pitch %d != %d\n",
util_format_short_name(testcase->format),
layout.width0, layout.height0, layout.depth0,
layout.nr_samples, l,
- layout.ubwc_slices[l].pitch,
+ fdl_ubwc_pitch(&layout, l),
testcase->layout.ubwc_slices[l].pitch);
ok = false;
}
bool is_3d;
/* Partially filled layout of input parameters and expected results. */
- struct fdl_layout layout;
+ struct {
+ uint32_t tile_mode : 2;
+ bool ubwc : 1;
+ uint32_t width0, height0, depth0;
+ uint32_t nr_samples;
+ struct {
+ uint32_t offset;
+ uint32_t pitch;
+ } slices[FDL_MAX_MIP_LEVELS];
+ struct {
+ uint32_t offset;
+ uint32_t pitch;
+ } ubwc_slices[FDL_MAX_MIP_LEVELS];
+ } layout;
};
bool fdl_test_layout(const struct testcase *testcase, int gpu_id);
u_minify(layout->depth0, level),
layout->cpp, layout->nr_samples,
level,
- slice->pitch,
+ fdl_pitch(layout, level),
slice->size0, ubwc_slice->size0,
- slice->size0 / slice->pitch,
+ slice->size0 / fdl_pitch(layout, level),
slice->offset, ubwc_slice->offset,
layout->layer_size, layout->ubwc_layer_size,
fdl_tile_mode(layout, level));
struct fdl_slice {
uint32_t offset; /* offset of first layer in slice */
- uint32_t pitch; /* pitch in bytes between rows. */
uint32_t size0; /* size of first layer in slice */
};
+/* parameters for explicit (imported) layout */
+struct fdl_explicit_layout {
+ uint32_t offset;
+ uint32_t pitch;
+};
+
/**
* Encapsulates the layout of a resource, including position of given 2d
* surface (layer, level) within. Or rather all the information needed
struct fdl_layout {
struct fdl_slice slices[FDL_MAX_MIP_LEVELS];
struct fdl_slice ubwc_slices[FDL_MAX_MIP_LEVELS];
+ uint32_t pitch0;
+ uint32_t ubwc_width0;
uint32_t layer_size;
uint32_t ubwc_layer_size; /* in bytes */
bool ubwc : 1;
uint32_t size; /* Size of the whole image, in bytes. */
uint32_t base_align; /* Alignment of the base address, in bytes. */
- uint8_t pitchalign; /* log2(pitchalign / 64) */
+ uint8_t pitchalign; /* log2(pitchalign) */
};
static inline uint32_t
return layout->cpp_shift;
}
+static inline uint32_t
+fdl_pitch(const struct fdl_layout *layout, unsigned level)
+{
+ return align(u_minify(layout->pitch0, level), 1 << layout->pitchalign);
+}
+
+#define RGB_TILE_WIDTH_ALIGNMENT 64
+#define RGB_TILE_HEIGHT_ALIGNMENT 16
+#define UBWC_PLANE_SIZE_ALIGNMENT 4096
+
+static inline uint32_t
+fdl_ubwc_pitch(const struct fdl_layout *layout, unsigned level)
+{
+ if (!layout->ubwc)
+ return 0;
+ return align(u_minify(layout->ubwc_width0, level), RGB_TILE_WIDTH_ALIGNMENT);
+}
+
static inline uint32_t
fdl_layer_stride(const struct fdl_layout *layout, unsigned level)
{
return layout->slices[level].size0;
}
+/* a2xx is special and needs PoT alignment for mipmaps: */
+static inline uint32_t
+fdl2_pitch(const struct fdl_layout *layout, unsigned level)
+{
+ uint32_t pitch = fdl_pitch(layout, level);
+ if (level)
+ pitch = util_next_power_of_two(pitch);
+ return pitch;
+}
+
+static inline uint32_t
+fdl2_pitch_pixels(const struct fdl_layout *layout, unsigned level)
+{
+ return fdl2_pitch(layout, level) >> fdl_cpp_shift(layout);
+}
+
static inline uint32_t
fdl_surface_offset(const struct fdl_layout *layout, unsigned level, unsigned layer)
{
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,
- struct fdl_slice *plane_layout);
+ struct fdl_explicit_layout *plane_layout);
+
+static inline void
+fdl_set_pitchalign(struct fdl_layout *layout, unsigned pitchalign)
+{
+ uint32_t nblocksx = util_format_get_nblocksx(layout->format, layout->width0);
+ layout->pitchalign = pitchalign;
+ layout->pitch0 = align(nblocksx * layout->cpp, 1 << pitchalign);
+}
void
fdl_dump_layout(struct fdl_layout *layout);
<value name="TFMT_NONE" value="0xff"/>
</enum>
-<enum name="a3xx_tex_fetchsize">
- <doc>
- Size pixel to fetch, in bytes. Doesn't seem to be required, setting
- it to 0x0 seems to work ok, but may be less optimal.
- </doc>
- <value name="TFETCH_DISABLE" value="0"/>
- <value name="TFETCH_1_BYTE" value="1"/>
- <value name="TFETCH_2_BYTE" value="2"/>
- <value name="TFETCH_4_BYTE" value="3"/>
- <value name="TFETCH_8_BYTE" value="4"/>
- <value name="TFETCH_16_BYTE" value="5"/>
-</enum>
-
<enum name="a3xx_color_fmt">
<value name="RB_R5G6B5_UNORM" value="0x00"/>
<value name="RB_R5G5B5A1_UNORM" value="0x01"/>
<reg32 offset="1" name="1">
<bitfield name="HEIGHT" low="0" high="13" type="uint"/>
<bitfield name="WIDTH" low="14" high="27" type="uint"/>
- <bitfield name="FETCHSIZE" low="28" high="31" type="a3xx_tex_fetchsize"/>
+ <!-- minimum pitch (for mipmap levels): log2(pitchalign / 16) -->
+ <bitfield name="PITCHALIGN" low="28" high="31" type="uint"/>
</reg32>
<reg32 offset="2" name="2">
<doc>INDX is index of texture address(es) in MIPMAP state block</doc>
<value name="TFMT4_NONE" value="0xff"/>
</enum>
-<enum name="a4xx_tex_fetchsize">
- <doc>
- Size pixel to fetch, in bytes. Doesn't seem to be required, setting
- it to 0x0 seems to work ok, but may be less optimal.
- </doc>
- <value name="TFETCH4_1_BYTE" value="0"/>
- <value name="TFETCH4_2_BYTE" value="1"/>
- <value name="TFETCH4_4_BYTE" value="2"/>
- <value name="TFETCH4_8_BYTE" value="3"/>
- <value name="TFETCH4_16_BYTE" value="4"/>
-</enum>
-
<enum name="a4xx_depth_format">
<value name="DEPTH4_NONE" value="0"/>
<value name="DEPTH4_16" value="1"/>
<bitfield name="WIDTH" low="15" high="29" type="uint"/>
</reg32>
<reg32 offset="2" name="2">
- <bitfield name="FETCHSIZE" low="0" high="3" type="a4xx_tex_fetchsize"/>
+ <!-- minimum pitch (for mipmap levels): log2(pitchalign / 32) -->
+ <bitfield name="PITCHALIGN" low="0" high="3" type="uint"/>
<doc>Pitch in bytes (so actually stride)</doc>
<bitfield name="PITCH" low="9" high="29" type="uint"/>
<bitfield name="SWAP" low="30" high="31" type="a3xx_color_swap"/>
<value value="0xff" name="TFMT5_NONE"/>
</enum>
-<enum name="a5xx_tex_fetchsize">
- <doc>
- Size pixel to fetch, in bytes. Doesn't seem to be required, setting
- it to 0x0 seems to work ok, but may be less optimal.
- </doc>
- <value name="TFETCH5_1_BYTE" value="0"/>
- <value name="TFETCH5_2_BYTE" value="1"/>
- <value name="TFETCH5_4_BYTE" value="2"/>
- <value name="TFETCH5_8_BYTE" value="3"/>
- <value name="TFETCH5_16_BYTE" value="4"/>
-</enum>
-
<enum name="a5xx_depth_format">
<value name="DEPTH5_NONE" value="0"/>
<value name="DEPTH5_16" value="1"/>
<bitfield name="HEIGHT" low="15" high="29" type="uint"/>
</reg32>
<reg32 offset="2" name="2">
- <bitfield name="FETCHSIZE" low="0" high="3" type="a5xx_tex_fetchsize"/>
+ <!-- minimum pitch (for mipmap levels): log2(pitchalign / 64) -->
+ <bitfield name="PITCHALIGN" low="0" high="3" type="uint"/>
<doc>Pitch in bytes (so actually stride)</doc>
<bitfield name="PITCH" low="7" high="28" type="uint"/>
<bitfield name="TYPE" low="29" high="30" type="a5xx_tex_type"/>
}
}
- struct fdl_slice plane_layout;
+ struct fdl_explicit_layout plane_layout;
if (plane_layouts) {
/* only expect simple 2D images for now */
uint64_t ubwc_addr = image->bo->iova + image->bo_offset +
fdl_ubwc_offset(layout, range->baseMipLevel, range->baseArrayLayer);
- uint32_t pitch = layout->slices[range->baseMipLevel].pitch;
- uint32_t ubwc_pitch = layout->ubwc_slices[range->baseMipLevel].pitch;
+ uint32_t pitch = fdl_pitch(layout, range->baseMipLevel);
+ uint32_t ubwc_pitch = fdl_ubwc_pitch(layout, range->baseMipLevel);
uint32_t layer_size = fdl_layer_stride(layout, range->baseMipLevel);
struct tu_native_format fmt = tu6_format_texture(format, layout->tile_mode);
A6XX_TEX_CONST_0_MIPLVLS(tu_get_levelCount(image, range) - 1);
iview->descriptor[1] = A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height);
iview->descriptor[2] =
- A6XX_TEX_CONST_2_PITCHALIGN(layout->pitchalign) |
+ A6XX_TEX_CONST_2_PITCHALIGN(layout->pitchalign - 6) |
A6XX_TEX_CONST_2_PITCH(pitch) |
A6XX_TEX_CONST_2_TYPE(tu6_tex_type(pCreateInfo->viewType, false));
iview->descriptor[3] = A6XX_TEX_CONST_3_ARRAY_PITCH(layer_size);
iview->descriptor[4] = base_addr[0];
iview->descriptor[5] |= base_addr[0] >> 32;
iview->descriptor[6] =
- A6XX_TEX_CONST_6_PLANE_PITCH(image->layout[1].slices[range->baseMipLevel].pitch);
+ A6XX_TEX_CONST_6_PLANE_PITCH(fdl_pitch(&image->layout[1], range->baseMipLevel));
iview->descriptor[7] = base_addr[1];
iview->descriptor[8] = base_addr[1] >> 32;
iview->descriptor[9] = base_addr[2];
pLayout->offset =
fdl_surface_offset(layout, pSubresource->mipLevel, pSubresource->arrayLayer);
pLayout->size = slice->size0;
- pLayout->rowPitch = slice->pitch;
+ pLayout->rowPitch = fdl_pitch(layout, pSubresource->mipLevel);
pLayout->arrayPitch = fdl_layer_stride(layout, pSubresource->mipLevel);
pLayout->depthPitch = slice->size0;
{
struct fd_ringbuffer *ring = batch->tile_fini;
struct fd_resource *rsc = fd_resource(psurf->texture);
- struct fdl_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);
enum pipe_format format = fd_gmem_restore_format(psurf->format);
- uint32_t pitch = slice->pitch >> fdl_cpp_shift(&rsc->layout);
+ uint32_t pitch = fdl2_pitch_pixels(&rsc->layout, psurf->u.tex.level);
assert((pitch & 31) == 0);
assert((offset & 0xfff) == 0);
{
struct fd_ringbuffer *ring = batch->gmem;
struct fd_resource *rsc = fd_resource(psurf->texture);
- struct fdl_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);
enum pipe_format format = fd_gmem_restore_format(psurf->format);
+
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
OUT_RING(ring, A2XX_RB_COLOR_INFO_BASE(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(slice->pitch >> fdl_cpp_shift(&rsc->layout)));
+ A2XX_SQ_TEX_0_PITCH(fdl2_pitch_pixels(&rsc->layout, psurf->u.tex.level)));
OUT_RELOC(ring, rsc->bo, offset,
A2XX_SQ_TEX_1_FORMAT(fd2_pipe2surface(format).format) |
A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL), 0);
return;
struct fd_resource *rsc = fd_resource(psurf->texture);
- struct fdl_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 pitch = slice->pitch >> fdl_cpp_shift(&rsc->layout);
+ uint32_t pitch = fdl2_pitch_pixels(&rsc->layout, psurf->u.tex.level);
assert((pitch & 31) == 0);
assert((offset & 0xfff) == 0);
{
struct pipe_resource *prsc = &rsc->base;
enum pipe_format format = rsc->base.format;
+ uint32_t height0 = util_format_get_nblocksy(format, prsc->height0);
uint32_t level, size = 0;
- uint32_t width = prsc->width0;
- uint32_t height = prsc->height0;
- uint32_t depth = prsc->depth0;
+
+ /* 32 pixel alignment */
+ fdl_set_pitchalign(&rsc->layout, fdl_cpp_shift(&rsc->layout) + 5);
for (level = 0; level <= prsc->last_level; level++) {
struct fdl_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;
- }
+ uint32_t pitch = fdl2_pitch(&rsc->layout, level);
+ uint32_t nblocksy = align(u_minify(height0, level), 32);
/* mipmaps have power of two sizes in memory */
- if (level) {
- width = util_next_power_of_two(width);
- height = util_next_power_of_two(height);
- }
+ if (level)
+ nblocksy = util_next_power_of_two(nblocksy);
- slice->pitch = util_format_get_nblocksx(format, width) * rsc->layout.cpp;
slice->offset = size;
+ slice->size0 = align(pitch * nblocksy, 4096);
- blocks = util_format_get_nblocks(format, width, height);
-
- /* 4k aligned size */
- slice->size0 = align(blocks * rsc->layout.cpp, 4096);
-
- size += slice->size0 * depth * prsc->array_size;
-
- width = u_minify(width, 1);
- height = u_minify(height, 1);
- depth = u_minify(depth, 1);
+ size += slice->size0 * u_minify(prsc->depth0, level) * prsc->array_size;
}
+
return size;
}
so->base.reference.count = 1;
so->base.context = pctx;
- struct fdl_slice *slice0 = fd_resource_slice(rsc, 0);
so->tex0 =
A2XX_SQ_TEX_0_SIGN_X(fmt.sign) |
A2XX_SQ_TEX_0_SIGN_Y(fmt.sign) |
A2XX_SQ_TEX_0_SIGN_Z(fmt.sign) |
A2XX_SQ_TEX_0_SIGN_W(fmt.sign) |
- A2XX_SQ_TEX_0_PITCH((slice0->pitch >> fdl_cpp_shift(&rsc->layout)) *
+ A2XX_SQ_TEX_0_PITCH(fdl2_pitch_pixels(&rsc->layout, 0) *
util_format_get_blockwidth(prsc->format)) |
COND(rsc->layout.tile_mode, A2XX_SQ_TEX_0_TILED);
so->tex1 =
A3XX_TEX_CONST_0_TYPE(A3XX_TEX_2D) |
fd3_tex_swiz(format, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W));
- OUT_RING(ring, A3XX_TEX_CONST_1_FETCHSIZE(TFETCH_DISABLE) |
- A3XX_TEX_CONST_1_WIDTH(psurf[i]->width) |
- A3XX_TEX_CONST_1_HEIGHT(psurf[i]->height));
+ OUT_RING(ring, A3XX_TEX_CONST_1_WIDTH(psurf[i]->width) |
+ A3XX_TEX_CONST_1_HEIGHT(psurf[i]->height));
OUT_RING(ring, A3XX_TEX_CONST_2_PITCH(fd_resource_pitch(rsc, lvl)) |
A3XX_TEX_CONST_2_INDX(BASETABLE_SZ * i));
OUT_RING(ring, 0x00000000);
return formats[format].swap;
}
-enum a3xx_tex_fetchsize
-fd3_pipe2fetchsize(enum pipe_format format)
-{
- if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
- format = PIPE_FORMAT_Z32_FLOAT;
- else if (util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_RGTC)
- format = PIPE_FORMAT_R8G8B8A8_UNORM;
- switch (util_format_get_blocksizebits(format) / util_format_get_blockwidth(format)) {
- case 8: return TFETCH_1_BYTE;
- case 16: return TFETCH_2_BYTE;
- case 32: return TFETCH_4_BYTE;
- case 64: return TFETCH_8_BYTE;
- case 128: return TFETCH_16_BYTE;
- default:
- debug_printf("Unknown block size for format %s: %d\n",
- util_format_name(format),
- util_format_get_blocksizebits(format));
- return TFETCH_DISABLE;
- }
-}
-
enum a3xx_color_fmt
fd3_fs_output_format(enum pipe_format format)
{
enum a3xx_vtx_fmt fd3_pipe2vtx(enum pipe_format format);
enum a3xx_tex_fmt fd3_pipe2tex(enum pipe_format format);
-enum a3xx_tex_fetchsize fd3_pipe2fetchsize(enum pipe_format format);
enum a3xx_color_fmt fd3_pipe2color(enum pipe_format format);
enum a3xx_color_fmt fd3_fs_output_format(enum pipe_format format);
enum a3xx_color_swap fd3_pipe2swap(enum pipe_format format);
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);
- uint32_t pitchalign = screen->gmem_alignw;
uint32_t level, size = 0;
- uint32_t width = prsc->width0;
- uint32_t height = prsc->height0;
- uint32_t depth = prsc->depth0;
+ uint32_t width0 = prsc->width0;
+
+ if (rsc->layout.tile_mode && prsc->target != PIPE_TEXTURE_CUBE)
+ width0 = util_next_power_of_two(width0);
+
+ /* 32 pixel alignment */
+ fdl_set_pitchalign(&rsc->layout, fdl_cpp_shift(&rsc->layout) + 5);
for (level = 0; level <= prsc->last_level; level++) {
struct fdl_slice *slice = fd_resource_slice(rsc, level);
- uint32_t blocks;
-
+ uint32_t pitch = fdl_pitch(&rsc->layout, level);
+ uint32_t height = u_minify(prsc->height0, level);
if (rsc->layout.tile_mode) {
- if (prsc->target != PIPE_TEXTURE_CUBE) {
- if (level == 0) {
- width = util_next_power_of_two(width);
- height = util_next_power_of_two(height);
- }
- width = MAX2(width, 8);
- height = MAX2(height, 4);
- // Multiplying by 4 is the result of the 4x4 tiling pattern.
- slice->pitch = width * 4;
- blocks = util_format_get_nblocks(format, width, height);
- } else {
- uint32_t twidth, theight;
- twidth = align(width, 8);
- theight = align(height, 4);
- // Multiplying by 4 is the result of the 4x4 tiling pattern.
- slice->pitch = twidth * 4;
- blocks = util_format_get_nblocks(format, twidth, theight);
- }
- } else {
- slice->pitch = width = align(width, pitchalign);
- blocks = util_format_get_nblocks(format, slice->pitch, height);
+ height = align(height, 4);
+ if (prsc->target != PIPE_TEXTURE_CUBE)
+ height = util_next_power_of_two(height);
}
- slice->pitch = util_format_get_nblocksx(format, slice->pitch) *
- rsc->layout.cpp;
+
+ uint32_t nblocksy = util_format_get_nblocksy(format, height);
slice->offset = size;
/* 1d array and 2d array textures must all have the same layer size
if (prsc->target == PIPE_TEXTURE_3D && (
level == 1 ||
(level > 1 && fd_resource_slice(rsc, level - 1)->size0 > 0xf000)))
- slice->size0 = align(blocks * rsc->layout.cpp, alignment);
+ slice->size0 = align(nblocksy * pitch, alignment);
else if (level == 0 || alignment == 1)
- slice->size0 = align(blocks * rsc->layout.cpp, alignment);
+ slice->size0 = align(nblocksy * pitch, alignment);
else
slice->size0 = fd_resource_slice(rsc, level - 1)->size0;
- size += slice->size0 * depth * prsc->array_size;
-
- width = u_minify(width, 1);
- height = u_minify(height, 1);
- depth = u_minify(depth, 1);
+ size += slice->size0 * u_minify(prsc->depth0, level) * prsc->array_size;
}
return size;
if (prsc->target == PIPE_BUFFER) {
lvl = 0;
so->texconst1 =
- A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
A3XX_TEX_CONST_1_WIDTH(cso->u.buf.size / util_format_get_blocksize(cso->format)) |
A3XX_TEX_CONST_1_HEIGHT(1);
} else {
so->texconst0 |= A3XX_TEX_CONST_0_MIPLVLS(miplevels);
so->texconst1 =
- A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
+ A3XX_TEX_CONST_1_PITCHALIGN(rsc->layout.pitchalign - 4) |
A3XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
A3XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
}
PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W));
OUT_RING(ring, A4XX_TEX_CONST_1_WIDTH(bufs[i]->width) |
A4XX_TEX_CONST_1_HEIGHT(bufs[i]->height));
- OUT_RING(ring, A4XX_TEX_CONST_2_PITCH(fd_resource_pitch(rsc, lvl)) |
- A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(format)));
+ OUT_RING(ring, A4XX_TEX_CONST_2_PITCH(fd_resource_pitch(rsc, lvl)));
OUT_RING(ring, 0x00000000);
OUT_RELOC(ring, rsc->bo, offset, 0, 0);
OUT_RING(ring, 0x00000000);
return formats[format].swap;
}
-enum a4xx_tex_fetchsize
-fd4_pipe2fetchsize(enum pipe_format format)
-{
- if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
- format = PIPE_FORMAT_Z32_FLOAT;
-
- if (util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_ASTC)
- return TFETCH4_16_BYTE;
-
- switch (util_format_get_blocksizebits(format) / util_format_get_blockwidth(format)) {
- case 8: return TFETCH4_1_BYTE;
- case 16: return TFETCH4_2_BYTE;
- case 32: return TFETCH4_4_BYTE;
- case 64: return TFETCH4_8_BYTE;
- case 96: return TFETCH4_1_BYTE; /* Does this matter? */
- case 128: return TFETCH4_16_BYTE;
- default:
- debug_printf("Unknown block size for format %s: %d\n",
- util_format_name(format),
- util_format_get_blocksizebits(format));
- return TFETCH4_1_BYTE;
- }
-}
-
enum a4xx_depth_format
fd4_pipe2depth(enum pipe_format format)
{
enum a4xx_tex_fmt fd4_pipe2tex(enum pipe_format format);
enum a4xx_color_fmt fd4_pipe2color(enum pipe_format format);
enum a3xx_color_swap fd4_pipe2swap(enum pipe_format format);
-enum a4xx_tex_fetchsize fd4_pipe2fetchsize(enum pipe_format format);
enum a4xx_depth_format fd4_pipe2depth(enum pipe_format format);
uint32_t fd4_tex_swiz(enum pipe_format format, unsigned swizzle_r,
{
struct pipe_resource *prsc = &rsc->base;
enum pipe_format format = prsc->format;
- enum util_format_layout layout = util_format_description(format)->layout;
uint32_t level, size = 0;
uint32_t width = prsc->width0;
uint32_t height = prsc->height0;
alignment = 1;
}
+ /* 32 pixel alignment */
+ fdl_set_pitchalign(&rsc->layout, fdl_cpp_shift(&rsc->layout) + 5);
+
for (level = 0; level <= prsc->last_level; level++) {
struct fdl_slice *slice = fd_resource_slice(rsc, level);
- uint32_t blocks;
+ uint32_t pitch = fdl_pitch(&rsc->layout, level);
+ uint32_t nblocksy = util_format_get_nblocksy(format, height);
- if (layout == UTIL_FORMAT_LAYOUT_ASTC)
- width = util_align_npot(width, 32 * util_format_get_blockwidth(format));
- else
- width = align(width, 32);
- slice->pitch = util_format_get_nblocksx(format, width) * rsc->layout.cpp;
slice->offset = size;
- blocks = util_format_get_nblocks(format, width, height);
+
/* 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
(level > 1 && fd_resource_slice(rsc, level - 1)->size0 <= 0xf000))
slice->size0 = fd_resource_slice(rsc, level - 1)->size0;
else
- slice->size0 = align(blocks * rsc->layout.cpp, alignment);
+ slice->size0 = align(nblocksy * pitch, alignment);
size += slice->size0 * depth * layers_in_level;
A4XX_TEX_CONST_1_WIDTH(elements) |
A4XX_TEX_CONST_1_HEIGHT(1);
so->texconst2 =
- A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(format)) |
A4XX_TEX_CONST_2_PITCH(elements * rsc->layout.cpp);
so->offset = cso->u.buf.offset;
} else {
A4XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
A4XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
so->texconst2 =
- A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(format)) |
+ A4XX_TEX_CONST_2_PITCHALIGN(rsc->layout.pitchalign - 5) |
A4XX_TEX_CONST_2_PITCH(fd_resource_pitch(rsc, lvl));
so->offset = fd_resource_offset(rsc, lvl, cso->u.tex.first_layer);
}
return formats[format].swap;
}
-// XXX possibly same as a4xx..
-enum a5xx_tex_fetchsize
-fd5_pipe2fetchsize(enum pipe_format format)
-{
- if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
- format = PIPE_FORMAT_Z32_FLOAT;
-
- if (util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_ASTC)
- return TFETCH5_16_BYTE;
-
- switch (util_format_get_blocksizebits(format) / util_format_get_blockwidth(format)) {
- case 8: return TFETCH5_1_BYTE;
- case 16: return TFETCH5_2_BYTE;
- case 32: return TFETCH5_4_BYTE;
- case 64: return TFETCH5_8_BYTE;
- case 96: return TFETCH5_1_BYTE; /* Does this matter? */
- case 128: return TFETCH5_16_BYTE;
- default:
- debug_printf("Unknown block size for format %s: %d\n",
- util_format_name(format),
- util_format_get_blocksizebits(format));
- return TFETCH5_1_BYTE;
- }
-}
-
enum a5xx_depth_format
fd5_pipe2depth(enum pipe_format format)
{
enum a5xx_tex_fmt fd5_pipe2tex(enum pipe_format format);
enum a5xx_color_fmt fd5_pipe2color(enum pipe_format format);
enum a3xx_color_swap fd5_pipe2swap(enum pipe_format format);
-enum a5xx_tex_fetchsize fd5_pipe2fetchsize(enum pipe_format format);
enum a5xx_depth_format fd5_pipe2depth(enum pipe_format format);
uint32_t fd5_tex_swiz(enum pipe_format format, unsigned swizzle_r,
struct fd5_image {
enum pipe_format pfmt;
enum a5xx_tex_fmt fmt;
- enum a5xx_tex_fetchsize fetchsize;
enum a5xx_tex_type type;
bool srgb;
uint32_t cpp;
img->pfmt = format;
img->fmt = fd5_pipe2tex(format);
- img->fetchsize = fd5_pipe2fetchsize(format);
img->type = fd5_tex_type(prsc->target);
img->srgb = util_format_is_srgb(format);
img->cpp = rsc->layout.cpp;
COND(img->srgb, A5XX_TEX_CONST_0_SRGB));
OUT_RING(ring, A5XX_TEX_CONST_1_WIDTH(img->width) |
A5XX_TEX_CONST_1_HEIGHT(img->height));
- OUT_RING(ring, A5XX_TEX_CONST_2_FETCHSIZE(img->fetchsize) |
- A5XX_TEX_CONST_2_TYPE(img->type) |
+ OUT_RING(ring, A5XX_TEX_CONST_2_TYPE(img->type) |
A5XX_TEX_CONST_2_PITCH(img->pitch));
OUT_RING(ring, A5XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch));
if (img->bo) {
A5XX_TEX_CONST_1_WIDTH(elements) |
A5XX_TEX_CONST_1_HEIGHT(1);
so->texconst2 =
- A5XX_TEX_CONST_2_FETCHSIZE(fd5_pipe2fetchsize(format)) |
A5XX_TEX_CONST_2_PITCH(elements * rsc->layout.cpp);
so->offset = cso->u.buf.offset;
} else {
A5XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
A5XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
so->texconst2 =
- A5XX_TEX_CONST_2_FETCHSIZE(fd5_pipe2fetchsize(format)) |
+ A5XX_TEX_CONST_2_PITCHALIGN(rsc->layout.pitchalign - 6) |
A5XX_TEX_CONST_2_PITCH(fd_resource_pitch(rsc, lvl));
so->offset = fd_resource_offset(rsc, lvl, cso->u.tex.first_layer);
}
if (fd_resource_ubwc_enabled(rsc, level)) {
OUT_RELOC(ring, rsc->bo, fd_resource_ubwc_offset(rsc, level, layer), 0, 0);
OUT_RING(ring,
- A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(rsc->layout.ubwc_slices[level].pitch) |
+ A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(fdl_ubwc_pitch(&rsc->layout, level)) |
A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(rsc->layout.ubwc_layer_size >> 2));
} else {
OUT_RING(ring, 0x00000000); /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
OUT_RING(ring, 0x00000000); /* texconst6 */
if (ubwc_enabled) {
- struct fdl_slice *ubwc_slice = &rsc->layout.ubwc_slices[img->level];
-
uint32_t block_width, block_height;
fdl6_get_ubwc_blockwidth(&rsc->layout, &block_width, &block_height);
OUT_RELOC(ring, rsc->bo, img->ubwc_offset, 0, 0);
OUT_RING(ring, A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(rsc->layout.ubwc_layer_size >> 2));
OUT_RING(ring,
- A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(ubwc_slice->pitch) |
+ A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(fdl_ubwc_pitch(&rsc->layout, img->level)) |
A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(img->width, block_width))) |
A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(img->height, block_height))));
} else {
OUT_RING(ring, 0x00000000);
if (ubwc_enabled) {
- struct fdl_slice *ubwc_slice = &rsc->layout.ubwc_slices[img->level];
OUT_RELOC(ring, rsc->bo, img->ubwc_offset, 0, 0);
OUT_RING(ring, A6XX_IBO_9_FLAG_BUFFER_ARRAY_PITCH(rsc->layout.ubwc_layer_size >> 2));
- OUT_RING(ring, A6XX_IBO_10_FLAG_BUFFER_PITCH(ubwc_slice->pitch));
+ OUT_RING(ring, A6XX_IBO_10_FLAG_BUFFER_PITCH(fdl_ubwc_pitch(&rsc->layout, img->level)));
} else {
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
fill_ubwc_buffer_sizes(struct fd_resource *rsc)
{
struct pipe_resource *prsc = &rsc->base;
- struct fdl_slice slice = *fd_resource_slice(rsc, 0);
+ struct fdl_explicit_layout explicit = {
+ .offset = rsc->layout.slices[0].offset,
+ .pitch = rsc->layout.pitch0,
+ };
/* limit things to simple single level 2d for now: */
if ((prsc->depth0 != 1) || (prsc->array_size != 1) || (prsc->last_level != 0))
if (!fdl6_layout(&rsc->layout, prsc->format, fd_resource_nr_samples(prsc),
prsc->width0, prsc->height0, prsc->depth0,
- prsc->last_level + 1, prsc->array_size, false, &slice))
+ prsc->last_level + 1, prsc->array_size, false, &explicit))
return -1;
if (rsc->layout.size > fd_bo_size(rsc->bo))
A6XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
A6XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
so->texconst2 =
- A6XX_TEX_CONST_2_PITCHALIGN(rsc->layout.pitchalign) |
+ A6XX_TEX_CONST_2_PITCHALIGN(rsc->layout.pitchalign - 6) |
A6XX_TEX_CONST_2_PITCH(fd_resource_pitch(rsc, lvl));
so->offset = fd_resource_offset(rsc, lvl, cso->u.tex.first_layer);
so->ubwc_offset = fd_resource_ubwc_offset(rsc, lvl, cso->u.tex.first_layer);
}
if (so->ubwc_enabled) {
- struct fdl_slice *ubwc_base_slice = &rsc->layout.ubwc_slices[lvl];
-
uint32_t block_width, block_height;
fdl6_get_ubwc_blockwidth(&rsc->layout, &block_width, &block_height);
so->texconst3 |= A6XX_TEX_CONST_3_FLAG | A6XX_TEX_CONST_3_TILE_ALL;
so->texconst9 |= A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(rsc->layout.ubwc_layer_size >> 2);
so->texconst10 |=
- A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(ubwc_base_slice->pitch) |
+ A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(fdl_ubwc_pitch(&rsc->layout, lvl)) |
A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(u_minify(prsc->width0, lvl), block_width))) |
A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(u_minify(prsc->height0, lvl), block_height)));
}
struct fd_resource *rsc = fd_resource(prsc);
struct fdl_layout *layout = &rsc->layout;
+ layout->format = prsc->format;
+
layout->width0 = prsc->width0;
layout->height0 = prsc->height0;
layout->depth0 = prsc->depth0;
goto fail;
rsc->internal_format = tmpl->format;
- slice->pitch = handle->stride;
+ rsc->layout.pitch0 = handle->stride;
slice->offset = handle->offset;
slice->size0 = handle->stride * prsc->height0;
if (is_a6xx(screen))
pitchalign = 64;
- if ((slice->pitch < align(prsc->width0 * rsc->layout.cpp, pitchalign)) ||
- (slice->pitch & (pitchalign - 1)))
+ if ((rsc->layout.pitch0 < align(prsc->width0 * rsc->layout.cpp, pitchalign)) ||
+ (rsc->layout.pitch0 & (pitchalign - 1)))
goto fail;
assert(rsc->layout.cpp);
static inline uint32_t
fd_resource_pitch(struct fd_resource *rsc, unsigned level)
{
- return fd_resource_slice(rsc, level)->pitch;
+ if (is_a2xx(fd_screen(rsc->base.screen)))
+ return fdl2_pitch(&rsc->layout, level);
+
+ return fdl_pitch(&rsc->layout, level);
}
/* get offset for specified mipmap level and texture/array layer */