aboutsummaryrefslogtreecommitdiffstats
path: root/src/freedreno
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno')
-rw-r--r--src/freedreno/vulkan/meson.build3
-rw-r--r--src/freedreno/vulkan/tu_blit.c298
-rw-r--r--src/freedreno/vulkan/tu_blit.h100
-rw-r--r--src/freedreno/vulkan/tu_cmd_buffer.c4
-rw-r--r--src/freedreno/vulkan/tu_formats.c4
-rw-r--r--src/freedreno/vulkan/tu_meta_blit.c54
-rw-r--r--src/freedreno/vulkan/tu_meta_copy.c651
-rw-r--r--src/freedreno/vulkan/tu_private.h2
8 files changed, 526 insertions, 590 deletions
diff --git a/src/freedreno/vulkan/meson.build b/src/freedreno/vulkan/meson.build
index 03079a14994..b5299232518 100644
--- a/src/freedreno/vulkan/meson.build
+++ b/src/freedreno/vulkan/meson.build
@@ -49,8 +49,11 @@ tu_format_table_c = custom_target(
)
libtu_files = files(
+ 'tu_blit.c',
+ 'tu_blit.h',
'tu_cmd_buffer.c',
'tu_cs.c',
+ 'tu_cs.h',
'tu_device.c',
'tu_descriptor_set.c',
'tu_descriptor_set.h',
diff --git a/src/freedreno/vulkan/tu_blit.c b/src/freedreno/vulkan/tu_blit.c
new file mode 100644
index 00000000000..33e0fd45a55
--- /dev/null
+++ b/src/freedreno/vulkan/tu_blit.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright © 2019 Valve Corporation
+ *
+ * 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 <[email protected]>
+ *
+ */
+
+#include "tu_blit.h"
+
+#include "a6xx.xml.h"
+#include "adreno_common.xml.h"
+#include "adreno_pm4.xml.h"
+
+#include "vk_format.h"
+
+#include "tu_cs.h"
+
+/* TODO:
+ * - Avoid disabling tiling for swapped formats
+ * (image_to_image copy doesn't deal with it)
+ * - Fix d24_unorm_s8_uint support & aspects
+ * - UBWC
+ */
+
+static VkFormat
+blit_copy_format(VkFormat format)
+{
+ switch (vk_format_get_blocksizebits(format)) {
+ case 8: return VK_FORMAT_R8_UINT;
+ case 16: return VK_FORMAT_R16_UINT;
+ case 32: return VK_FORMAT_R8G8B8A8_UINT;
+ case 64: return VK_FORMAT_R32G32_UINT;
+ case 96: return VK_FORMAT_R32G32B32_UINT;
+ case 128:return VK_FORMAT_R32G32B32A32_UINT;
+ default:
+ unreachable("unhandled format size");
+ }
+}
+
+static uint32_t
+blit_image_info(const struct tu_blit_surf *img, bool src, bool stencil_read)
+{
+ const struct tu_native_format *fmt = tu6_get_native_format(img->fmt);
+ enum a6xx_color_fmt rb = fmt->rb;
+ enum a3xx_color_swap swap = img->tiled ? WZYX : fmt->swap;
+ if (rb == RB6_R10G10B10A2_UNORM && src)
+ rb = RB6_R10G10B10A2_FLOAT16;
+ if (rb == RB6_X8Z24_UNORM)
+ rb = RB6_Z24_UNORM_S8_UINT;
+
+ if (stencil_read)
+ swap = XYZW;
+
+ return A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb) |
+ A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(img->tile_mode) |
+ A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(swap) |
+ COND(vk_format_is_srgb(img->fmt), A6XX_SP_PS_2D_SRC_INFO_SRGB);
+}
+
+static void
+emit_blit_step(struct tu_cmd_buffer *cmdbuf, const struct tu_blit *blt)
+{
+ struct tu_cs *cs = &cmdbuf->cs;
+
+ tu_cs_reserve_space(cmdbuf->device, cs, 52);
+
+ enum a6xx_color_fmt fmt = tu6_get_native_format(blt->dst.fmt)->rb;
+ if (fmt == RB6_X8Z24_UNORM)
+ fmt = RB6_Z24_UNORM_S8_UINT;
+
+ enum a6xx_2d_ifmt ifmt = tu6_rb_fmt_to_ifmt(fmt);
+
+ if (vk_format_is_srgb(blt->dst.fmt)) {
+ assert(ifmt == R2D_UNORM8);
+ ifmt = R2D_UNORM8_SRGB;
+ }
+
+ uint32_t blit_cntl = A6XX_RB_2D_BLIT_CNTL_ROTATE(blt->rotation) |
+ A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT(fmt) | /* not required? */
+ COND(fmt == RB6_Z24_UNORM_S8_UINT, A6XX_RB_2D_BLIT_CNTL_D24S8) |
+ A6XX_RB_2D_BLIT_CNTL_MASK(0xf) |
+ A6XX_RB_2D_BLIT_CNTL_IFMT(ifmt);
+
+ tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
+ tu_cs_emit(&cmdbuf->cs, blit_cntl);
+
+ tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
+ tu_cs_emit(&cmdbuf->cs, blit_cntl);
+
+ /*
+ * Emit source:
+ */
+ tu_cs_emit_pkt4(cs, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
+ tu_cs_emit(cs, blit_image_info(&blt->src, true, blt->stencil_read) |
+ A6XX_SP_PS_2D_SRC_INFO_SAMPLES(tu_msaa_samples(blt->src.samples)) |
+ /* TODO: should disable this bit for integer formats ? */
+ COND(blt->src.samples > 1, A6XX_SP_PS_2D_SRC_INFO_SAMPLES_AVERAGE) |
+ COND(blt->filter, A6XX_SP_PS_2D_SRC_INFO_FILTER) |
+ 0x500000);
+ tu_cs_emit(cs, A6XX_SP_PS_2D_SRC_SIZE_WIDTH(blt->src.x + blt->src.width) |
+ A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(blt->src.y + blt->src.height));
+ tu_cs_emit_qw(cs, blt->src.va);
+ tu_cs_emit(cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(blt->src.pitch));
+
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+
+ /*
+ * Emit destination:
+ */
+ tu_cs_emit_pkt4(cs, REG_A6XX_RB_2D_DST_INFO, 9);
+ tu_cs_emit(cs, blit_image_info(&blt->dst, false, false));
+ tu_cs_emit_qw(cs, blt->dst.va);
+ tu_cs_emit(cs, A6XX_RB_2D_DST_SIZE_PITCH(blt->dst.pitch));
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+ tu_cs_emit(cs, 0x00000000);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
+ tu_cs_emit(cs, A6XX_GRAS_2D_SRC_TL_X_X(blt->src.x));
+ tu_cs_emit(cs, A6XX_GRAS_2D_SRC_BR_X_X(blt->src.x + blt->src.width - 1));
+ tu_cs_emit(cs, A6XX_GRAS_2D_SRC_TL_Y_Y(blt->src.y));
+ tu_cs_emit(cs, A6XX_GRAS_2D_SRC_BR_Y_Y(blt->src.y + blt->src.height - 1));
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_2D_DST_TL, 2);
+ tu_cs_emit(cs, A6XX_GRAS_2D_DST_TL_X(blt->dst.x) |
+ A6XX_GRAS_2D_DST_TL_Y(blt->dst.y));
+ tu_cs_emit(cs, A6XX_GRAS_2D_DST_BR_X(blt->dst.x + blt->dst.width - 1) |
+ A6XX_GRAS_2D_DST_BR_Y(blt->dst.y + blt->dst.height - 1));
+
+ tu_cs_emit_pkt7(cs, CP_EVENT_WRITE, 1);
+ tu_cs_emit(cs, 0x3f);
+ tu_cs_emit_wfi(cs);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
+ tu_cs_emit(cs, 0);
+
+ if (fmt == RB6_R10G10B10A2_UNORM)
+ fmt = RB6_R16G16B16A16_FLOAT;
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
+ tu_cs_emit(cs, COND(vk_format_is_sint(blt->src.fmt), A6XX_SP_2D_SRC_FORMAT_SINT) |
+ COND(vk_format_is_uint(blt->src.fmt), A6XX_SP_2D_SRC_FORMAT_UINT) |
+ A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(fmt) |
+ COND(ifmt == R2D_UNORM8_SRGB, A6XX_SP_2D_SRC_FORMAT_SRGB) |
+ A6XX_SP_2D_SRC_FORMAT_MASK(0xf));
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
+ tu_cs_emit(cs, 0x01000000);
+
+ tu_cs_emit_pkt7(cs, CP_BLIT, 1);
+ tu_cs_emit(cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
+
+ tu_cs_emit_wfi(cs);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
+ tu_cs_emit(cs, 0);
+}
+
+void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt, bool copy)
+{
+ if (copy) {
+ blt->stencil_read =
+ blt->dst.fmt == VK_FORMAT_R8_UINT &&
+ blt->src.fmt == VK_FORMAT_D24_UNORM_S8_UINT;
+
+ assert(vk_format_get_blocksize(blt->dst.fmt) ==
+ vk_format_get_blocksize(blt->src.fmt) || blt->stencil_read);
+ assert(blt->src.samples == blt->dst.samples);
+
+ if (vk_format_is_compressed(blt->src.fmt)) {
+ unsigned block_width = vk_format_get_blockwidth(blt->src.fmt);
+ unsigned block_height = vk_format_get_blockheight(blt->src.fmt);
+
+ blt->src.pitch /= block_width;
+ blt->src.x /= block_width;
+ blt->src.y /= block_height;
+
+ /* for image_to_image copy, width/height is on the src format */
+ blt->dst.width = blt->src.width = DIV_ROUND_UP(blt->src.width, block_width);
+ blt->dst.height = blt->src.height = DIV_ROUND_UP(blt->src.height, block_height);
+ }
+
+ if (vk_format_is_compressed(blt->dst.fmt)) {
+ unsigned block_width = vk_format_get_blockwidth(blt->dst.fmt);
+ unsigned block_height = vk_format_get_blockheight(blt->dst.fmt);
+
+ blt->dst.pitch /= block_width;
+ blt->dst.x /= block_width;
+ blt->dst.y /= block_height;
+ }
+
+ blt->src.fmt = blit_copy_format(blt->src.fmt);
+ blt->dst.fmt = blit_copy_format(blt->dst.fmt);
+
+ /* TODO: does this work correctly with tiling/etc ? */
+ blt->src.x *= blt->src.samples;
+ blt->dst.x *= blt->dst.samples;
+ blt->src.width *= blt->src.samples;
+ blt->dst.width *= blt->dst.samples;
+ blt->src.samples = 1;
+ blt->dst.samples = 1;
+ } else {
+ assert(blt->dst.samples == 1);
+ }
+
+ tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 18);
+
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, LRZ_FLUSH, false);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, PC_CCU_INVALIDATE_COLOR, false);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, PC_CCU_INVALIDATE_DEPTH, false);
+
+ /* buffer copy setup */
+ tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
+ tu_cs_emit(&cmdbuf->cs, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
+
+ for (unsigned layer = 0; layer < blt->layers; layer++) {
+ if ((blt->src.va & 63) || (blt->src.pitch & 63)) {
+ /* per line copy path (buffer_to_image) */
+ assert(copy && !blt->src.tiled);
+ struct tu_blit line_blt = *blt;
+ uint64_t src_va = line_blt.src.va + blt->src.pitch * blt->src.y;
+
+ line_blt.src.y = 0;
+ line_blt.src.pitch = 0;
+ line_blt.src.height = 1;
+ line_blt.dst.height = 1;
+
+ for (unsigned y = 0; y < blt->src.height; y++) {
+ line_blt.src.x = blt->src.x + (src_va & 63) / vk_format_get_blocksize(blt->src.fmt);
+ line_blt.src.va = src_va & ~63;
+
+ emit_blit_step(cmdbuf, &line_blt);
+
+ line_blt.dst.y++;
+ src_va += blt->src.pitch;
+ }
+ } else if ((blt->dst.va & 63) || (blt->dst.pitch & 63)) {
+ /* per line copy path (image_to_buffer) */
+ assert(copy && !blt->dst.tiled);
+ struct tu_blit line_blt = *blt;
+ uint64_t dst_va = line_blt.dst.va + blt->dst.pitch * blt->dst.y;
+
+ line_blt.dst.y = 0;
+ line_blt.dst.pitch = 0;
+ line_blt.src.height = 1;
+ line_blt.dst.height = 1;
+
+ for (unsigned y = 0; y < blt->src.height; y++) {
+ line_blt.dst.x = blt->dst.x + (dst_va & 63) / vk_format_get_blocksize(blt->dst.fmt);
+ line_blt.dst.va = dst_va & ~63;
+
+ emit_blit_step(cmdbuf, &line_blt);
+
+ line_blt.src.y++;
+ dst_va += blt->dst.pitch;
+ }
+ } else {
+ emit_blit_step(cmdbuf, blt);
+ }
+ blt->dst.va += blt->dst.layer_size;
+ blt->src.va += blt->src.layer_size;
+ }
+
+ tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 17);
+
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
+ tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_INVALIDATE, false);
+}
diff --git a/src/freedreno/vulkan/tu_blit.h b/src/freedreno/vulkan/tu_blit.h
new file mode 100644
index 00000000000..1f4967e845f
--- /dev/null
+++ b/src/freedreno/vulkan/tu_blit.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2019 Valve Corporation
+ *
+ * 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 <[email protected]>
+ *
+ */
+
+#ifndef TU_BLIT_H
+#define TU_BLIT_H
+
+#include "tu_private.h"
+
+#include "vk_format.h"
+
+struct tu_blit_surf {
+ VkFormat fmt;
+ enum a6xx_tile_mode tile_mode;
+ bool tiled;
+ uint64_t va;
+ uint32_t pitch, layer_size;
+ uint32_t x, y;
+ uint32_t width, height;
+ unsigned samples;
+};
+
+static inline struct tu_blit_surf
+tu_blit_surf(struct tu_image *img,
+ VkImageSubresourceLayers subres,
+ const VkOffset3D *offsets)
+{
+ return (struct tu_blit_surf) {
+ .fmt = img->vk_format,
+ .tile_mode = tu6_get_image_tile_mode(img, subres.mipLevel),
+ .tiled = img->tile_mode != TILE6_LINEAR,
+ .va = img->bo->iova + img->bo_offset + img->levels[subres.mipLevel].offset +
+ subres.baseArrayLayer * img->layer_size +
+ MIN2(offsets[0].z, offsets[1].z) * img->levels[subres.mipLevel].size,
+ .pitch = img->levels[subres.mipLevel].pitch * vk_format_get_blocksize(img->vk_format) * img->samples,
+ .layer_size = img->type == VK_IMAGE_TYPE_3D ? img->levels[subres.mipLevel].size : img->layer_size,
+ .x = MIN2(offsets[0].x, offsets[1].x),
+ .y = MIN2(offsets[0].y, offsets[1].y),
+ .width = abs(offsets[1].x - offsets[0].x),
+ .height = abs(offsets[1].y - offsets[0].y),
+ .samples = img->samples,
+ };
+}
+
+static inline struct tu_blit_surf
+tu_blit_surf_ext(struct tu_image *image,
+ VkImageSubresourceLayers subres,
+ VkOffset3D offset,
+ VkExtent3D extent)
+{
+ return tu_blit_surf(image, subres, (VkOffset3D[]) {
+ offset, {.x = offset.x + extent.width,
+ .y = offset.y + extent.height,
+ .z = offset.z}
+ });
+}
+
+static inline struct tu_blit_surf
+tu_blit_surf_whole(struct tu_image *image)
+{
+ return tu_blit_surf(image, (VkImageSubresourceLayers){}, (VkOffset3D[]) {
+ {}, {image->extent.width, image->extent.height}
+ });
+}
+
+struct tu_blit {
+ struct tu_blit_surf dst;
+ struct tu_blit_surf src;
+ uint32_t layers;
+ bool filter;
+ bool stencil_read;
+ enum a6xx_rotation rotation;
+};
+
+void tu_blit(struct tu_cmd_buffer *cmdbuf, struct tu_blit *blt, bool copy);
+
+#endif /* TU_BLIT_H */
diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c
index d701ae5fba7..3043740626f 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.c
+++ b/src/freedreno/vulkan/tu_cmd_buffer.c
@@ -314,8 +314,8 @@ tu_tiling_config_get_tile(const struct tu_tiling_config *tiling,
: tile->begin.y + tiling->tile0.extent.height;
}
-static enum a3xx_msaa_samples
-tu6_msaa_samples(uint32_t samples)
+enum a3xx_msaa_samples
+tu_msaa_samples(uint32_t samples)
{
switch (samples) {
case 1:
diff --git a/src/freedreno/vulkan/tu_formats.c b/src/freedreno/vulkan/tu_formats.c
index 7e68d6103cd..6b762441fbe 100644
--- a/src/freedreno/vulkan/tu_formats.c
+++ b/src/freedreno/vulkan/tu_formats.c
@@ -645,8 +645,8 @@ tu_physical_device_get_format_properties(
}
if (native_fmt->rb >= 0) {
- linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
- tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+ tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
}
end:
diff --git a/src/freedreno/vulkan/tu_meta_blit.c b/src/freedreno/vulkan/tu_meta_blit.c
index da5ff6b12b7..d624eef88b4 100644
--- a/src/freedreno/vulkan/tu_meta_blit.c
+++ b/src/freedreno/vulkan/tu_meta_blit.c
@@ -23,7 +23,49 @@
#include "tu_private.h"
-#include "nir/nir_builder.h"
+#include "tu_blit.h"
+
+static void
+tu_blit_image(struct tu_cmd_buffer *cmdbuf,
+ struct tu_image *src_image,
+ struct tu_image *dst_image,
+ const VkImageBlit *info,
+ VkFilter filter)
+{
+ static const enum a6xx_rotation rotate[2][2] = {
+ {ROTATE_0, ROTATE_HFLIP},
+ {ROTATE_VFLIP, ROTATE_180},
+ };
+ bool mirror_x = (info->srcOffsets[1].x < info->srcOffsets[0].x) !=
+ (info->dstOffsets[1].x < info->dstOffsets[0].x);
+ bool mirror_y = (info->srcOffsets[1].y < info->srcOffsets[0].y) !=
+ (info->dstOffsets[1].y < info->dstOffsets[0].y);
+ bool mirror_z = (info->srcOffsets[1].z < info->srcOffsets[0].z) !=
+ (info->dstOffsets[1].z < info->dstOffsets[0].z);
+
+ if (mirror_z) {
+ tu_finishme("blit z mirror\n");
+ return;
+ }
+
+ if (info->srcOffsets[1].z - info->srcOffsets[0].z !=
+ info->dstOffsets[1].z - info->dstOffsets[0].z) {
+ tu_finishme("blit z filter\n");
+ return;
+ }
+ assert(info->dstSubresource.layerCount == info->srcSubresource.layerCount);
+
+ struct tu_blit blt = {
+ .dst = tu_blit_surf(dst_image, info->dstSubresource, info->dstOffsets),
+ .src = tu_blit_surf(src_image, info->srcSubresource, info->srcOffsets),
+ .layers = MAX2(info->srcOffsets[1].z - info->srcOffsets[0].z,
+ info->dstSubresource.layerCount),
+ .filter = filter == VK_FILTER_LINEAR,
+ .rotation = rotate[mirror_y][mirror_x],
+ };
+
+ tu_blit(cmdbuf, &blt, false);
+}
void
tu_CmdBlitImage(VkCommandBuffer commandBuffer,
@@ -36,4 +78,14 @@ tu_CmdBlitImage(VkCommandBuffer commandBuffer,
VkFilter filter)
{
+ TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, commandBuffer);
+ TU_FROM_HANDLE(tu_image, src_image, srcImage);
+ TU_FROM_HANDLE(tu_image, dst_image, destImage);
+
+ tu_bo_list_add(&cmdbuf->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
+ tu_bo_list_add(&cmdbuf->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
+
+ for (uint32_t i = 0; i < regionCount; ++i) {
+ tu_blit_image(cmdbuf, src_image, dst_image, pRegions + i, filter);
+ }
}
diff --git a/src/freedreno/vulkan/tu_meta_copy.c b/src/freedreno/vulkan/tu_meta_copy.c
index fbd5dfdec9a..616151b751f 100644
--- a/src/freedreno/vulkan/tu_meta_copy.c
+++ b/src/freedreno/vulkan/tu_meta_copy.c
@@ -30,13 +30,7 @@
#include "vk_format.h"
#include "tu_cs.h"
-
-/*
- * TODO:
- * - 3D textures
- * - compressed image formats (need to divide offset/extent)
- * - Fix d24_unorm_s8_uint support & aspects
- */
+#include "tu_blit.h"
static uint32_t
blit_control(enum a6xx_color_fmt fmt)
@@ -47,29 +41,6 @@ blit_control(enum a6xx_color_fmt fmt)
return blit_cntl;
}
-static uint32_t tu6_sp_2d_src_format(VkFormat format)
-{
- const struct vk_format_description *desc = vk_format_description(format);
- uint32_t reg = 0xf000 | A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(tu6_get_native_format(format)->rb);
-
- int channel = vk_format_get_first_non_void_channel(format);
- if (channel < 0) {
- /* TODO special format. */
- return reg;
- }
- if (desc->channel[channel].normalized) {
- if (desc->channel[channel].type == VK_FORMAT_TYPE_SIGNED)
- reg |= A6XX_SP_2D_SRC_FORMAT_SINT;
- reg |= A6XX_SP_2D_SRC_FORMAT_NORM;
- } else if (desc->channel[channel].pure_integer) {
- if (desc->channel[channel].type == VK_FORMAT_TYPE_SIGNED)
- reg |= A6XX_SP_2D_SRC_FORMAT_SINT;
- else
- reg |= A6XX_SP_2D_SRC_FORMAT_UINT;
- }
- return reg;
-}
-
static void
tu_dma_prepare(struct tu_cmd_buffer *cmdbuf)
{
@@ -90,32 +61,6 @@ tu_dma_prepare(struct tu_cmd_buffer *cmdbuf)
tu_cs_emit(&cmdbuf->cs, 0x10000000);
}
-/* Always use UINT formats to avoid precision issues.
- *
- * Example failure it avoids:
- * - dEQP-VK.api.copy_and_blit.core.image_to_image.all_formats.color.r16_unorm.r16_unorm.general_general
- */
-static VkFormat
-tu_canonical_copy_format(VkFormat format)
-{
- switch (vk_format_get_blocksizebits(format)) {
- case 8:
- return VK_FORMAT_R8_UINT;
- case 16:
- return VK_FORMAT_R16_UINT;
- case 32:
- return VK_FORMAT_R32_UINT;
- case 64:
- return VK_FORMAT_R32G32_UINT;
- case 96:
- return VK_FORMAT_R32G32B32_UINT;
- case 128:
- return VK_FORMAT_R32G32B32A32_UINT;
- default:
- unreachable("unhandled format size");
- }
-}
-
static void
tu_copy_buffer(struct tu_cmd_buffer *cmdbuf,
struct tu_bo *src_bo,
@@ -249,548 +194,80 @@ tu_copy_buffer(struct tu_cmd_buffer *cmdbuf,
tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
}
-static void
-tu_copy_buffer_to_image_step(struct tu_cmd_buffer *cmdbuf,
- struct tu_buffer *src_buffer,
- struct tu_image *dst_image,
- const VkBufferImageCopy *copy_info,
- VkFormat format,
- uint32_t layer,
- uint64_t src_va)
+static struct tu_blit_surf
+tu_blit_buffer(struct tu_buffer *buffer,
+ VkFormat format,
+ const VkBufferImageCopy *info)
{
- const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
+ if (info->imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
+ format = VK_FORMAT_R8_UINT;
- uint64_t dst_va = dst_image->bo->iova + dst_image->bo_offset + dst_image->layer_size * layer + dst_image->levels[copy_info->imageSubresource.mipLevel].offset;
- unsigned dst_pitch = dst_image->levels[copy_info->imageSubresource.mipLevel].pitch *
+ unsigned pitch = (info->bufferRowLength ?: info->imageExtent.width) *
vk_format_get_blocksize(format);
- unsigned src_pitch;
- unsigned src_offset = 0;
- if (copy_info->imageExtent.height == 1) {
- /* Can't find this in the spec, but not having it is sort of insane? */
- assert(src_va % vk_format_get_blocksize(format) == 0);
-
- src_offset = (src_va & 63) / vk_format_get_blocksize(format);
- src_va &= ~63;
-
- src_pitch = align((src_offset + copy_info->imageExtent.width) * vk_format_get_blocksize(format), 64);
- } else {
- unsigned src_pixel_stride = copy_info->bufferRowLength
- ? copy_info->bufferRowLength
- : copy_info->imageExtent.width;
- src_pitch = src_pixel_stride * vk_format_get_blocksize(format);
- assert(!(src_pitch & 63));
- assert(!(src_va & 63));
- }
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 48);
-
- /*
- * Emit source:
- */
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
- tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt) |
- A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR) |
- A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) |
- 0x500000);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_offset + copy_info->imageExtent.width) |
- A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
- copy_info->imageExtent.height)); /* SP_PS_2D_SRC_SIZE */
- tu_cs_emit_qw(&cmdbuf->cs, src_va);
- tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch));
-
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- /*
- * Emit destination:
- */
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_DST_INFO, 9);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt) |
- A6XX_RB_2D_DST_INFO_TILE_MODE(dst_image->tile_mode) |
- A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
- tu_cs_emit_qw(&cmdbuf->cs, dst_va);
- tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch));
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_X_X(src_offset));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_SRC_BR_X_X(src_offset + copy_info->imageExtent.width - 1));
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_Y_Y(0));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info->imageExtent.height - 1));
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_DST_TL, 2);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_DST_TL_X(copy_info->imageOffset.x) |
- A6XX_GRAS_2D_DST_TL_Y(copy_info->imageOffset.y));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_DST_BR_X(copy_info->imageOffset.x +
- copy_info->imageExtent.width - 1) |
- A6XX_GRAS_2D_DST_BR_Y(copy_info->imageOffset.y +
- copy_info->imageExtent.height - 1));
-
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
- tu_cs_emit(&cmdbuf->cs, 0x3f);
- tu_cs_emit_wfi(&cmdbuf->cs);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
- tu_cs_emit(&cmdbuf->cs, 0);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
- tu_cs_emit(&cmdbuf->cs, tu6_sp_2d_src_format(format));
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
- tu_cs_emit(&cmdbuf->cs, 0x01000000);
-
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_BLIT, 1);
- tu_cs_emit(&cmdbuf->cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
-
- tu_cs_emit_wfi(&cmdbuf->cs);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
- tu_cs_emit(&cmdbuf->cs, 0);
+ return (struct tu_blit_surf) {
+ .fmt = format,
+ .tile_mode = TILE6_LINEAR,
+ .va = buffer->bo->iova + buffer->bo_offset + info->bufferOffset,
+ .pitch = pitch,
+ .layer_size = (info->bufferImageHeight ?: info->imageExtent.height) * pitch / vk_format_get_blockwidth(format) / vk_format_get_blockheight(format),
+ .width = info->imageExtent.width,
+ .height = info->imageExtent.height,
+ .samples = 1,
+ };
}
static void
tu_copy_buffer_to_image(struct tu_cmd_buffer *cmdbuf,
struct tu_buffer *src_buffer,
struct tu_image *dst_image,
- const VkBufferImageCopy *copy_info)
-{
- tu_bo_list_add(&cmdbuf->bo_list, src_buffer->bo, MSM_SUBMIT_BO_READ);
- tu_bo_list_add(&cmdbuf->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
-
- /* general setup */
- tu_dma_prepare(cmdbuf);
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 6);
-
- /* buffer copy setup */
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
- tu_cs_emit(&cmdbuf->cs, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
-
- VkFormat format = tu_canonical_copy_format(dst_image->vk_format);
- const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
-
- const uint32_t blit_cntl = blit_control(rb_fmt) | 0x20000000;
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
- tu_cs_emit(&cmdbuf->cs, blit_cntl);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
- tu_cs_emit(&cmdbuf->cs, blit_cntl);
-
- unsigned src_pixel_stride = copy_info->bufferRowLength
- ? copy_info->bufferRowLength
- : copy_info->imageExtent.width;
- unsigned cpp = vk_format_get_blocksize(format);
- unsigned src_pitch = src_pixel_stride * cpp;
-
- for (unsigned layer_offset = 0; layer_offset < copy_info->imageSubresource.layerCount; ++layer_offset) {
- unsigned layer = copy_info->imageSubresource.baseArrayLayer + layer_offset;
- uint64_t src_va = src_buffer->bo->iova + src_buffer->bo_offset + copy_info->bufferOffset + layer_offset * copy_info->bufferImageHeight * src_pitch;
-
- if ((src_pitch & 63) || (src_va & 63)) {
- /* Do a per line copy */
- VkBufferImageCopy line_copy_info = *copy_info;
- line_copy_info.imageExtent.height = 1;
- for (unsigned r = 0; r < copy_info->imageExtent.height; ++r) {
- /*
- * if src_va is not aligned the line copy will need to adjust. Give it
- * room to do so.
- */
- unsigned max_width = 16384 - (src_va & 0x3f) ? 64 : 0;
- line_copy_info.imageOffset.x = copy_info->imageOffset.x;
- line_copy_info.imageExtent.width = copy_info->imageExtent.width;
-
- for (unsigned c = 0; c < copy_info->imageExtent.width; c += max_width) {
- tu_copy_buffer_to_image_step(cmdbuf, src_buffer, dst_image, &line_copy_info, format, layer, src_va + c * cpp);
-
- line_copy_info.imageOffset.x += max_width;
- line_copy_info.imageExtent.width -= max_width;
- }
-
- line_copy_info.imageOffset.y++;
- src_va += src_pitch;
- }
- } else {
- tu_copy_buffer_to_image_step(cmdbuf, src_buffer, dst_image, copy_info, format, layer, src_va);
- }
- }
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 15);
-
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
-}
-
-static void
-tu_copy_image_to_buffer_step(struct tu_cmd_buffer *cmdbuf,
- struct tu_image *src_image,
- struct tu_buffer *dst_buffer,
- const VkBufferImageCopy *copy_info,
- VkFormat format,
- uint32_t layer,
- uint64_t dst_va)
+ const VkBufferImageCopy *info)
{
- const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
-
- uint64_t src_va = src_image->bo->iova + src_image->bo_offset + src_image->layer_size * layer + src_image->levels[copy_info->imageSubresource.mipLevel].offset;
- unsigned src_pitch = src_image->levels[copy_info->imageSubresource.mipLevel].pitch *
- vk_format_get_blocksize(format);
-
- unsigned dst_pitch;
- unsigned dst_offset = 0;
- if (copy_info->imageExtent.height == 1) {
- /* Can't find this in the spec, but not having it is sort of insane? */
- assert(dst_va % vk_format_get_blocksize(format) == 0);
-
- dst_offset = (dst_va & 63) / vk_format_get_blocksize(format);
- dst_va &= ~63;
-
- dst_pitch = align((dst_offset + copy_info->imageExtent.width) * vk_format_get_blocksize(format), 64);
- } else {
- unsigned dst_pixel_stride = copy_info->bufferRowLength
- ? copy_info->bufferRowLength
- : copy_info->imageExtent.width;
- dst_pitch = dst_pixel_stride * vk_format_get_blocksize(format);
- assert(!(dst_pitch & 63));
- assert(!(dst_va & 63));
+ if (info->imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT &&
+ vk_format_get_blocksize(dst_image->vk_format) == 4) {
+ tu_finishme("aspect mask\n");
+ return;
}
-
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 48);
-
- /*
- * Emit source:
- */
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt) |
- A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src_image->tile_mode) |
- A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) | 0x500000);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_image->extent.width) |
- A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
- src_image->extent.height)); /* SP_PS_2D_SRC_SIZE */
- tu_cs_emit_qw(&cmdbuf->cs, src_va);
- tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch));
-
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- /*
- * Emit destination:
- */
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_DST_INFO, 9);
- tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt) |
- A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR) |
- A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
- tu_cs_emit_qw(&cmdbuf->cs, dst_va);
- tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch));
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_X_X(copy_info->imageOffset.x));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_SRC_BR_X_X(copy_info->imageOffset.x +
- copy_info->imageExtent.width - 1));
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_Y_Y(copy_info->imageOffset.y));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info->imageOffset.y +
- copy_info->imageExtent.height - 1));
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_DST_TL, 2);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_DST_TL_X(dst_offset) | A6XX_GRAS_2D_DST_TL_Y(0));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_DST_BR_X(dst_offset + copy_info->imageExtent.width - 1) |
- A6XX_GRAS_2D_DST_BR_Y(copy_info->imageExtent.height - 1));
-
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
- tu_cs_emit(&cmdbuf->cs, 0x3f);
- tu_cs_emit_wfi(&cmdbuf->cs);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
- tu_cs_emit(&cmdbuf->cs, 0);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
- tu_cs_emit(&cmdbuf->cs, tu6_sp_2d_src_format(format));
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
- tu_cs_emit(&cmdbuf->cs, 0x01000000);
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_BLIT, 1);
- tu_cs_emit(&cmdbuf->cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
-
- tu_cs_emit_wfi(&cmdbuf->cs);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
- tu_cs_emit(&cmdbuf->cs, 0);
+ tu_blit(cmdbuf, &(struct tu_blit) {
+ .dst = tu_blit_surf_ext(dst_image, info->imageSubresource, info->imageOffset, info->imageExtent),
+ .src = tu_blit_buffer(src_buffer, dst_image->vk_format, info),
+ .layers = MAX2(info->imageExtent.depth, info->imageSubresource.layerCount),
+ }, true);
}
static void
tu_copy_image_to_buffer(struct tu_cmd_buffer *cmdbuf,
struct tu_image *src_image,
struct tu_buffer *dst_buffer,
- const VkBufferImageCopy *copy_info)
+ const VkBufferImageCopy *info)
{
- tu_bo_list_add(&cmdbuf->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
- tu_bo_list_add(&cmdbuf->bo_list, dst_buffer->bo, MSM_SUBMIT_BO_WRITE);
-
- /* general setup */
- tu_dma_prepare(cmdbuf);
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 6);
-
- /* buffer copy setup */
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
- tu_cs_emit(&cmdbuf->cs, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
-
- VkFormat format = tu_canonical_copy_format(src_image->vk_format);
- const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
-
- unsigned dst_pixel_stride = copy_info->bufferRowLength
- ? copy_info->bufferRowLength
- : copy_info->imageExtent.width;
- unsigned cpp = vk_format_get_blocksize(format);
- unsigned dst_pitch = dst_pixel_stride * cpp;
-
-
- const uint32_t blit_cntl = blit_control(rb_fmt) | 0x20000000;
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
- tu_cs_emit(&cmdbuf->cs, blit_cntl);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
- tu_cs_emit(&cmdbuf->cs, blit_cntl);
-
- for (unsigned layer_offset = 0; layer_offset < copy_info->imageSubresource.layerCount; ++layer_offset) {
- unsigned layer = copy_info->imageSubresource.baseArrayLayer + layer_offset;
- uint64_t dst_va = dst_buffer->bo->iova + dst_buffer->bo_offset + copy_info->bufferOffset + layer_offset * copy_info->bufferImageHeight * dst_pitch;
-
- if ((dst_pitch & 63) || (dst_va & 63)) {
- /* Do a per line copy */
- VkBufferImageCopy line_copy_info = *copy_info;
- line_copy_info.imageExtent.height = 1;
- for (unsigned r = 0; r < copy_info->imageExtent.height; ++r) {
- /*
- * if dst_va is not aligned the line copy will need to adjust. Give it
- * room to do so.
- */
- unsigned max_width = 16384 - (dst_va & 0x3f) ? 64 : 0;
- line_copy_info.imageOffset.x = copy_info->imageOffset.x;
- line_copy_info.imageExtent.width = copy_info->imageExtent.width;
-
- for (unsigned c = 0; c < copy_info->imageExtent.width; c += max_width) {
- tu_copy_image_to_buffer_step(cmdbuf, src_image, dst_buffer, &line_copy_info, format, layer, dst_va + c * cpp);
-
- line_copy_info.imageOffset.x += max_width;
- line_copy_info.imageExtent.width -= max_width;
- }
-
- line_copy_info.imageOffset.y++;
- dst_va += dst_pitch;
- }
- } else {
- tu_copy_image_to_buffer_step(cmdbuf, src_image, dst_buffer, copy_info, format, layer, dst_va);
- }
- }
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 15);
-
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
-}
-
-static void
-tu_copy_image_to_image_step(struct tu_cmd_buffer *cmdbuf,
- struct tu_image *src_image,
- struct tu_image *dst_image,
- const VkImageCopy *copy_info,
- VkFormat format,
- uint32_t layer_offset)
-{
- const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
-
- unsigned src_layer =
- copy_info->srcSubresource.baseArrayLayer + layer_offset;
- uint64_t src_va =
- src_image->bo->iova + src_image->bo_offset +
- src_image->layer_size * src_layer +
- src_image->levels[copy_info->srcSubresource.mipLevel].offset;
- unsigned src_pitch =
- src_image->levels[copy_info->srcSubresource.mipLevel].pitch *
- vk_format_get_blocksize(format);
-
- unsigned dst_layer =
- copy_info->dstSubresource.baseArrayLayer + layer_offset;
- uint64_t dst_va =
- dst_image->bo->iova + dst_image->bo_offset +
- dst_image->layer_size * dst_layer +
- dst_image->levels[copy_info->dstSubresource.mipLevel].offset;
- unsigned dst_pitch =
- src_image->levels[copy_info->dstSubresource.mipLevel].pitch *
- vk_format_get_blocksize(format);
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 48);
-
- /*
- * Emit source:
- */
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt) |
- A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src_image->tile_mode) |
- A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) | 0x500000);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_image->extent.width) |
- A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
- src_image->extent.height)); /* SP_PS_2D_SRC_SIZE */
- tu_cs_emit_qw(&cmdbuf->cs, src_va);
- tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch));
-
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- /*
- * Emit destination:
- */
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_DST_INFO, 9);
- tu_cs_emit(&cmdbuf->cs,
- A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt) |
- A6XX_RB_2D_DST_INFO_TILE_MODE(dst_image->tile_mode) |
- A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
- tu_cs_emit_qw(&cmdbuf->cs, dst_va);
- tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch));
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
- tu_cs_emit(&cmdbuf->cs, 0x00000000);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_X_X(copy_info->srcOffset.x));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_SRC_BR_X_X(copy_info->srcOffset.x +
- copy_info->extent.width - 1));
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_Y_Y(copy_info->srcOffset.y));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info->srcOffset.y +
- copy_info->extent.height - 1));
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_DST_TL, 2);
- tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_DST_TL_X(copy_info->dstOffset.x) |
- A6XX_GRAS_2D_DST_TL_Y(copy_info->dstOffset.y));
- tu_cs_emit(&cmdbuf->cs,
- A6XX_GRAS_2D_DST_BR_X(copy_info->dstOffset.x +
- copy_info->extent.width - 1) |
- A6XX_GRAS_2D_DST_BR_Y(copy_info->dstOffset.y +
- copy_info->extent.height - 1));
-
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
- tu_cs_emit(&cmdbuf->cs, 0x3f);
- tu_cs_emit_wfi(&cmdbuf->cs);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
- tu_cs_emit(&cmdbuf->cs, 0);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
- tu_cs_emit(&cmdbuf->cs, tu6_sp_2d_src_format(format));
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
- tu_cs_emit(&cmdbuf->cs, 0x01000000);
-
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_BLIT, 1);
- tu_cs_emit(&cmdbuf->cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
-
- tu_cs_emit_wfi(&cmdbuf->cs);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
- tu_cs_emit(&cmdbuf->cs, 0);
+ tu_blit(cmdbuf, &(struct tu_blit) {
+ .dst = tu_blit_buffer(dst_buffer, src_image->vk_format, info),
+ .src = tu_blit_surf_ext(src_image, info->imageSubresource, info->imageOffset, info->imageExtent),
+ .layers = MAX2(info->imageExtent.depth, info->imageSubresource.layerCount),
+ }, true);
}
static void
tu_copy_image_to_image(struct tu_cmd_buffer *cmdbuf,
struct tu_image *src_image,
struct tu_image *dst_image,
- const VkImageCopy *copy_info)
+ const VkImageCopy *info)
{
- /* TODO:
- * - Handle 3D images.
- * - In some cases where src and dst format are different this may
- * have tiling implications. Not sure if things happen correctly
- * in that case.
- */
-
- tu_bo_list_add(&cmdbuf->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
- tu_bo_list_add(&cmdbuf->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
-
- /* general setup */
- tu_dma_prepare(cmdbuf);
-
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 6);
-
- /* buffer copy setup */
- tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
- tu_cs_emit(&cmdbuf->cs, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
-
- VkFormat format = tu_canonical_copy_format(src_image->vk_format);
- const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
- const uint32_t blit_cntl = blit_control(rb_fmt) | 0x20000000;
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
- tu_cs_emit(&cmdbuf->cs, blit_cntl);
-
- tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
- tu_cs_emit(&cmdbuf->cs, blit_cntl);
-
- for (unsigned layer_offset = 0;
- layer_offset < copy_info->srcSubresource.layerCount; ++layer_offset) {
- tu_copy_image_to_image_step(cmdbuf, src_image, dst_image, copy_info,
- format, layer_offset);
+ if ((info->dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT &&
+ vk_format_get_blocksize(dst_image->vk_format) == 4) ||
+ (info->srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT &&
+ vk_format_get_blocksize(src_image->vk_format) == 4)) {
+ tu_finishme("aspect mask\n");
+ return;
}
- tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 15);
-
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
- tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
+ tu_blit(cmdbuf, &(struct tu_blit) {
+ .dst = tu_blit_surf_ext(dst_image, info->dstSubresource, info->dstOffset, info->extent),
+ .src = tu_blit_surf_ext(src_image, info->srcSubresource, info->srcOffset, info->extent),
+ .layers = info->extent.depth,
+ }, true);
}
void
@@ -821,14 +298,15 @@ tu_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
uint32_t regionCount,
const VkBufferImageCopy *pRegions)
{
- TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
- TU_FROM_HANDLE(tu_image, dest_image, destImage);
+ TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, commandBuffer);
+ TU_FROM_HANDLE(tu_image, dst_image, destImage);
TU_FROM_HANDLE(tu_buffer, src_buffer, srcBuffer);
- for (unsigned i = 0; i < regionCount; ++i) {
- tu_copy_buffer_to_image(cmd_buffer, src_buffer, dest_image,
- pRegions + i);
- }
+ tu_bo_list_add(&cmdbuf->bo_list, src_buffer->bo, MSM_SUBMIT_BO_READ);
+ tu_bo_list_add(&cmdbuf->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
+
+ for (unsigned i = 0; i < regionCount; ++i)
+ tu_copy_buffer_to_image(cmdbuf, src_buffer, dst_image, pRegions + i);
}
void
@@ -839,14 +317,15 @@ tu_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
uint32_t regionCount,
const VkBufferImageCopy *pRegions)
{
- TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
+ TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, commandBuffer);
TU_FROM_HANDLE(tu_image, src_image, srcImage);
TU_FROM_HANDLE(tu_buffer, dst_buffer, destBuffer);
- for (unsigned i = 0; i < regionCount; ++i) {
- tu_copy_image_to_buffer(cmd_buffer, src_image, dst_buffer,
- pRegions + i);
- }
+ tu_bo_list_add(&cmdbuf->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
+ tu_bo_list_add(&cmdbuf->bo_list, dst_buffer->bo, MSM_SUBMIT_BO_WRITE);
+
+ for (unsigned i = 0; i < regionCount; ++i)
+ tu_copy_image_to_buffer(cmdbuf, src_image, dst_buffer, pRegions + i);
}
void
@@ -858,11 +337,13 @@ tu_CmdCopyImage(VkCommandBuffer commandBuffer,
uint32_t regionCount,
const VkImageCopy *pRegions)
{
- TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
+ TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, commandBuffer);
TU_FROM_HANDLE(tu_image, src_image, srcImage);
- TU_FROM_HANDLE(tu_image, dest_image, destImage);
+ TU_FROM_HANDLE(tu_image, dst_image, destImage);
- for (uint32_t i = 0; i < regionCount; ++i) {
- tu_copy_image_to_image(cmd_buffer, src_image, dest_image, pRegions + i);
- }
+ tu_bo_list_add(&cmdbuf->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
+ tu_bo_list_add(&cmdbuf->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
+
+ for (uint32_t i = 0; i < regionCount; ++i)
+ tu_copy_image_to_image(cmdbuf, src_image, dst_image, pRegions + i);
}
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index 405fa20b4f5..eb043ccf562 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -1299,6 +1299,8 @@ tu_get_levelCount(const struct tu_image *image,
enum a6xx_tile_mode
tu6_get_image_tile_mode(struct tu_image *image, int level);
+enum a3xx_msaa_samples
+tu_msaa_samples(uint32_t samples);
struct tu_image_view
{