diff options
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_simulator_validate.c')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_simulator_validate.c | 143 |
1 files changed, 112 insertions, 31 deletions
diff --git a/src/gallium/drivers/vc4/vc4_simulator_validate.c b/src/gallium/drivers/vc4/vc4_simulator_validate.c index c062d8a25bd..00ec301dbb6 100644 --- a/src/gallium/drivers/vc4/vc4_simulator_validate.c +++ b/src/gallium/drivers/vc4/vc4_simulator_validate.c @@ -47,6 +47,53 @@ void *validated, \ void *untrusted + +/** Return the width in pixels of a 64-byte microtile. */ +static uint32_t +utile_width(int cpp) +{ + switch (cpp) { + case 1: + case 2: + return 8; + case 4: + return 4; + case 8: + return 2; + default: + DRM_ERROR("unknown cpp: %d\n", cpp); + return 1; + } +} + +/** Return the height in pixels of a 64-byte microtile. */ +static uint32_t +utile_height(int cpp) +{ + switch (cpp) { + case 1: + return 8; + case 2: + case 4: + case 8: + return 4; + default: + DRM_ERROR("unknown cpp: %d\n", cpp); + return 1; + } +} + +/** + * The texture unit decides what tiling format a particular miplevel is using + * this function, so we lay out our miptrees accordingly. + */ +static bool +size_is_lt(uint32_t width, uint32_t height, int cpp) +{ + return (width <= 4 * utile_width(cpp) || + height <= 4 * utile_height(cpp)); +} + static bool vc4_use_bo(struct exec_info *exec, uint32_t hindex, @@ -105,47 +152,50 @@ check_tex_size(struct exec_info *exec, struct drm_gem_cma_object *fbo, uint32_t offset, uint8_t tiling_format, uint32_t width, uint32_t height, uint8_t cpp) { - uint32_t width_align, height_align; - uint32_t aligned_row_len, aligned_h, size; + uint32_t aligned_width, aligned_height, stride, size; + uint32_t utile_w = utile_width(cpp); + uint32_t utile_h = utile_height(cpp); + + /* The values are limited by the packet/texture parameter bitfields, + * so we don't need to worry as much about integer overflow. + */ + BUG_ON(width > 65535); + BUG_ON(height > 65535); switch (tiling_format) { case VC4_TILING_FORMAT_LINEAR: - width_align = 16; - height_align = 1; + aligned_width = roundup(width, 16 / cpp); + aligned_height = height; break; case VC4_TILING_FORMAT_T: - width_align = 128; - height_align = 32; + aligned_width = roundup(width, utile_w * 8); + aligned_height = roundup(height, utile_h * 8); break; case VC4_TILING_FORMAT_LT: - width_align = 16; - height_align = 4; + aligned_width = roundup(width, utile_w); + aligned_height = roundup(height, utile_h); break; default: DRM_ERROR("buffer tiling %d unsupported\n", tiling_format); return false; } - /* The values are limited by the packet/texture parameter bitfields, - * so we don't need to worry as much about integer overflow. - */ - BUG_ON(width > 65535); - BUG_ON(height > 65535); - - aligned_row_len = roundup(width * cpp, width_align); - aligned_h = roundup(height, height_align); + stride = aligned_width * cpp; - if (INT_MAX / aligned_row_len < aligned_h) { - DRM_ERROR("Overflow in fbo size (%d * %d)\n", - aligned_row_len, aligned_h); + if (INT_MAX / stride < aligned_height) { + DRM_ERROR("Overflow in fbo size (%dx%d -> %dx%d)\n", + width, height, + aligned_width, aligned_height); return false; } - size = aligned_row_len * aligned_h; + size = stride * aligned_height; if (size + offset < size || size + offset > fbo->base.size) { - DRM_ERROR("Overflow in %dx%d fbo size (%d + %d > %d)\n", - width, height, size, offset, fbo->base.size); + DRM_ERROR("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %d)\n", + width, height, + aligned_width, aligned_height, + size, offset, fbo->base.size); return false; } @@ -706,8 +756,8 @@ reloc_tex(struct exec_info *exec, uint32_t miplevels = (p0 & 15); uint32_t width = (p1 >> 8) & 2047; uint32_t height = (p1 >> 20) & 2047; - uint32_t cpp, tiling_format; - int i; + uint32_t cpp, tiling_format, utile_w, utile_h; + uint32_t i; enum vc4_texture_data_type type; if (width == 0) @@ -751,12 +801,16 @@ reloc_tex(struct exec_info *exec, DRM_ERROR("Texture format %d unsupported\n", type); return false; } + utile_w = utile_width(cpp); + utile_h = utile_height(cpp); if (type == VC4_TEXTURE_TYPE_RGBA32R) { tiling_format = VC4_TILING_FORMAT_LINEAR; } else { - DRM_ERROR("Tiling formats not yet supported\n"); - return false; + if (size_is_lt(width, height, cpp)) + tiling_format = VC4_TILING_FORMAT_LT; + else + tiling_format = VC4_TILING_FORMAT_T; } if (!vc4_use_bo(exec, texture_handle_index, VC4_MODE_RENDER, &tex)) @@ -771,17 +825,44 @@ reloc_tex(struct exec_info *exec, * sure there is actually space in the BO. */ for (i = 1; i <= miplevels; i++) { - uint32_t level_width = align(max(width >> i, 1), 16 / cpp); - uint32_t level_height = max(height >> i, 1); - uint32_t level_size = level_width * level_height * cpp; + uint32_t level_width = max(width >> i, 1u); + uint32_t level_height = max(height >> i, 1u); + uint32_t aligned_width, aligned_height; + uint32_t level_size; + + /* Once the levels get small enough, they drop from T to LT. */ + if (tiling_format == VC4_TILING_FORMAT_T && + size_is_lt(level_width, level_height, cpp)) { + tiling_format = VC4_TILING_FORMAT_LT; + } + + switch (tiling_format) { + case VC4_TILING_FORMAT_T: + aligned_width = roundup(level_width, utile_w * 8); + aligned_height = roundup(level_height, utile_h * 8); + break; + case VC4_TILING_FORMAT_LT: + aligned_width = roundup(level_width, utile_w); + aligned_height = roundup(level_height, utile_h); + break; + default: + aligned_width = roundup(level_width, 16 / cpp); + aligned_height = height; + break; + } + + level_size = aligned_width * cpp * aligned_height; if (offset < level_size) { - DRM_ERROR("Level %d (%dx%d) size %db overflowed " - "buffer bounds (offset %d)\n", + DRM_ERROR("Level %d (%dx%d -> %dx%d) size %db " + "overflowed buffer bounds (offset %d)\n", i, level_width, level_height, + aligned_width, aligned_height, level_size, offset); return false; } + + offset -= level_size; } *validated_p0 = tex->paddr + p0; |