meta_emit_blit(struct radv_cmd_buffer *cmd_buffer,
struct radv_image *src_image,
struct radv_image_view *src_iview,
- VkOffset3D src_offset,
- VkExtent3D src_extent,
+ VkOffset3D src_offset_0,
+ VkOffset3D src_offset_1,
struct radv_image *dest_image,
struct radv_image_view *dest_iview,
- VkOffset3D dest_offset,
- VkExtent3D dest_extent,
+ VkOffset3D dest_offset_0,
+ VkOffset3D dest_offset_1,
+ VkRect2D dest_box,
VkFilter blit_filter)
{
struct radv_device *device = cmd_buffer->device;
unsigned vb_size = 3 * sizeof(*vb_data);
vb_data[0] = (struct blit_vb_data) {
.pos = {
- dest_offset.x,
- dest_offset.y,
+ dest_offset_0.x,
+ dest_offset_0.y,
},
.tex_coord = {
- (float)(src_offset.x) / (float)src_iview->extent.width,
- (float)(src_offset.y) / (float)src_iview->extent.height,
- (float)src_offset.z / (float)src_iview->extent.depth,
+ (float)src_offset_0.x / (float)src_iview->extent.width,
+ (float)src_offset_0.y / (float)src_iview->extent.height,
+ (float)src_offset_0.z / (float)src_iview->extent.depth,
},
};
vb_data[1] = (struct blit_vb_data) {
.pos = {
- dest_offset.x,
- dest_offset.y + dest_extent.height,
+ dest_offset_0.x,
+ dest_offset_1.y,
},
.tex_coord = {
- (float)src_offset.x / (float)src_iview->extent.width,
- (float)(src_offset.y + src_extent.height) /
- (float)src_iview->extent.height,
- (float)src_offset.z / (float)src_iview->extent.depth,
+ (float)src_offset_0.x / (float)src_iview->extent.width,
+ (float)src_offset_1.y / (float)src_iview->extent.height,
+ (float)src_offset_0.z / (float)src_iview->extent.depth,
},
};
vb_data[2] = (struct blit_vb_data) {
.pos = {
- dest_offset.x + dest_extent.width,
- dest_offset.y,
+ dest_offset_1.x,
+ dest_offset_0.y,
},
.tex_coord = {
- (float)(src_offset.x + src_extent.width) / (float)src_iview->extent.width,
- (float)src_offset.y / (float)src_iview->extent.height,
- (float)src_offset.z / (float)src_iview->extent.depth,
+ (float)src_offset_1.x / (float)src_iview->extent.width,
+ (float)src_offset_0.y / (float)src_iview->extent.height,
+ (float)src_offset_0.z / (float)src_iview->extent.depth,
},
};
radv_cmd_buffer_upload_data(cmd_buffer, vb_size, 16, vb_data, &offset);
.renderPass = device->meta_state.blit.render_pass[fs_key],
.framebuffer = fb,
.renderArea = {
- .offset = { dest_offset.x, dest_offset.y },
- .extent = { dest_extent.width, dest_extent.height },
+ .offset = { dest_box.offset.x, dest_box.offset.y },
+ .extent = { dest_box.extent.width, dest_box.extent.height },
},
.clearValueCount = 0,
.pClearValues = NULL,
.renderPass = device->meta_state.blit.depth_only_rp,
.framebuffer = fb,
.renderArea = {
- .offset = { dest_offset.x, dest_offset.y },
- .extent = { dest_extent.width, dest_extent.height },
+ .offset = { dest_box.offset.x, dest_box.offset.y },
+ .extent = { dest_box.extent.width, dest_box.extent.height },
},
.clearValueCount = 0,
.pClearValues = NULL,
.renderPass = device->meta_state.blit.stencil_only_rp,
.framebuffer = fb,
.renderArea = {
- .offset = { dest_offset.x, dest_offset.y },
- .extent = { dest_extent.width, dest_extent.height },
- },
+ .offset = { dest_box.offset.x, dest_box.offset.y },
+ .extent = { dest_box.extent.width, dest_box.extent.height },
+ },
.clearValueCount = 0,
.pClearValues = NULL,
}, VK_SUBPASS_CONTENTS_INLINE);
&cmd_buffer->pool->alloc);
}
+static bool
+flip_coords(unsigned *src0, unsigned *src1, unsigned *dst0, unsigned *dst1)
+{
+ bool flip = false;
+ if (*src0 > *src1) {
+ unsigned tmp = *src0;
+ *src0 = *src1;
+ *src1 = tmp;
+ flip = !flip;
+ }
+
+ if (*dst0 > *dst1) {
+ unsigned tmp = *dst0;
+ *dst0 = *dst1;
+ *dst1 = tmp;
+ flip = !flip;
+ }
+ return flip;
+}
+
void radv_CmdBlitImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
},
cmd_buffer, VK_IMAGE_USAGE_SAMPLED_BIT);
- if (pRegions[r].dstOffsets[1].x < pRegions[r].dstOffsets[0].x ||
- pRegions[r].dstOffsets[1].y < pRegions[r].dstOffsets[0].y ||
- pRegions[r].srcOffsets[1].x < pRegions[r].srcOffsets[0].x ||
- pRegions[r].srcOffsets[1].y < pRegions[r].srcOffsets[0].y)
- radv_finishme("FINISHME: Allow flipping in blits");
+ unsigned dst_start, dst_end;
+ if (dest_image->type == VK_IMAGE_TYPE_3D) {
+ assert(dst_res->baseArrayLayer == 0);
+ dst_start = pRegions[r].dstOffsets[0].z;
+ dst_end = pRegions[r].dstOffsets[1].z;
+ } else {
+ dst_start = dst_res->baseArrayLayer;
+ dst_end = dst_start + dst_res->layerCount;
+ }
- const VkExtent3D dest_extent = {
- .width = pRegions[r].dstOffsets[1].x - pRegions[r].dstOffsets[0].x,
- .height = pRegions[r].dstOffsets[1].y - pRegions[r].dstOffsets[0].y,
- .depth = 1,
- };
+ unsigned src_start, src_end;
+ if (src_image->type == VK_IMAGE_TYPE_3D) {
+ assert(src_res->baseArrayLayer == 0);
+ src_start = pRegions[r].srcOffsets[0].z;
+ src_end = pRegions[r].srcOffsets[1].z;
+ } else {
+ src_start = src_res->baseArrayLayer;
+ src_end = src_start + src_res->layerCount;
+ }
- const VkExtent3D src_extent = {
- .width = pRegions[r].srcOffsets[1].x - pRegions[r].srcOffsets[0].x,
- .height = pRegions[r].srcOffsets[1].y - pRegions[r].srcOffsets[0].y,
- .depth = pRegions[r].srcOffsets[1].z - pRegions[r].srcOffsets[0].z,
- };
+ bool flip_z = flip_coords(&src_start, &src_end, &dst_start, &dst_end);
+ float src_z_step = (float)(src_end + 1 - src_start) /
+ (float)(dst_end + 1 - dst_start);
+
+ if (flip_z) {
+ src_start = src_end;
+ src_z_step *= -1;
+ }
+ unsigned src_x0 = pRegions[r].srcOffsets[0].x;
+ unsigned src_x1 = pRegions[r].srcOffsets[1].x;
+ unsigned dst_x0 = pRegions[r].dstOffsets[0].x;
+ unsigned dst_x1 = pRegions[r].dstOffsets[1].x;
- if (src_res->layerCount > 1)
- radv_finishme("FINISHME: copy multiple array layers");
+ unsigned src_y0 = pRegions[r].srcOffsets[0].y;
+ unsigned src_y1 = pRegions[r].srcOffsets[1].y;
+ unsigned dst_y0 = pRegions[r].dstOffsets[0].y;
+ unsigned dst_y1 = pRegions[r].dstOffsets[1].y;
+
+ VkRect2D dest_box;
+ dest_box.offset.x = MIN2(dst_x0, dst_x1);
+ dest_box.offset.y = MIN2(dst_y0, dst_y1);
+ dest_box.extent.width = abs(dst_x1 - dst_x0);
+ dest_box.extent.height = abs(dst_y1 - dst_y0);
struct radv_image_view dest_iview;
unsigned usage;
else
usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- for (unsigned i = pRegions[r].dstOffsets[0].z; i < pRegions[r].dstOffsets[1].z; i++) {
-
- const VkOffset3D dest_offset = {
- .x = pRegions[r].dstOffsets[0].x,
- .y = pRegions[r].dstOffsets[0].y,
- .z = i,
+ const unsigned num_layers = dst_end - dst_start;
+ for (unsigned i = 0; i < num_layers; i++) {
+ const VkOffset3D dest_offset_0 = {
+ .x = dst_x0,
+ .y = dst_y0,
+ .z = dst_start + i ,
+ };
+ const VkOffset3D dest_offset_1 = {
+ .x = dst_x1,
+ .y = dst_y1,
+ .z = dst_start + i ,
+ };
+ VkOffset3D src_offset_0 = {
+ .x = src_x0,
+ .y = src_y0,
+ .z = src_start + i * src_z_step,
};
- VkOffset3D src_offset = {
- .x = pRegions[r].srcOffsets[0].x,
- .y = pRegions[r].srcOffsets[0].y,
- .z = i,
+ VkOffset3D src_offset_1 = {
+ .x = src_x1,
+ .y = src_y1,
+ .z = src_start + i * src_z_step,
};
const uint32_t dest_array_slice =
radv_meta_get_iview_layer(dest_image, dst_res,
- &dest_offset);
+ &dest_offset_0);
radv_image_view_init(&dest_iview, cmd_buffer->device,
&(VkImageViewCreateInfo) {
cmd_buffer, usage);
meta_emit_blit(cmd_buffer,
src_image, &src_iview,
- src_offset, src_extent,
+ src_offset_0, src_offset_1,
dest_image, &dest_iview,
- dest_offset, dest_extent,
+ dest_offset_0, dest_offset_1,
+ dest_box,
filter);
}
}