render/vulkan: extract pixel copy into separate function

This commit is contained in:
Simon Ser 2023-11-24 19:23:32 +01:00
parent a59dd1d567
commit 50b471e035

View file

@ -36,6 +36,40 @@ static VkImageAspectFlagBits mem_plane_aspect(unsigned i) {
} }
} }
static void copy_pixels(char *vmap, const char *vdata, uint32_t tex_width,
uint32_t stride, uint32_t size, const pixman_region32_t *region,
const struct wlr_pixel_format_info *format_info) {
int rects_len = 0;
const pixman_box32_t *rects = pixman_region32_rectangles(region, &rects_len);
char *map = vmap;
for (int i = 0; i < rects_len; i++) {
pixman_box32_t rect = rects[i];
uint32_t width = rect.x2 - rect.x1;
uint32_t height = rect.y2 - rect.y1;
uint32_t src_x = rect.x1;
uint32_t src_y = rect.y1;
uint32_t packed_stride = (uint32_t)pixel_format_info_min_stride(format_info, width);
// write data into staging buffer span
const char *pdata = vdata; // data iterator
pdata += stride * src_y;
pdata += format_info->bytes_per_block * src_x;
if (src_x == 0 && width == tex_width && stride == packed_stride) {
memcpy(map, pdata, packed_stride * height);
map += packed_stride * height;
} else {
for (unsigned i = 0u; i < height; ++i) {
memcpy(map, pdata, packed_stride);
pdata += stride;
map += packed_stride;
}
}
}
assert((uint32_t)(map - vmap) == size);
}
// Will transition the texture to shaderReadOnlyOptimal layout for reading // Will transition the texture to shaderReadOnlyOptimal layout for reading
// from fragment shader later on // from fragment shader later on
static bool write_pixels(struct wlr_vk_texture *texture, static bool write_pixels(struct wlr_vk_texture *texture,
@ -83,19 +117,7 @@ static bool write_pixels(struct wlr_vk_texture *texture,
uint64_t timeline_point = ++renderer->upload_timeline_point; uint64_t timeline_point = ++renderer->upload_timeline_point;
void *vmap; uint32_t buf_off = span.alloc.start;
res = vkMapMemory(dev, span.buffer->memory, span.alloc.start,
bsize, 0, &vmap);
if (res != VK_SUCCESS) {
wlr_vk_error("vkMapMemory", res);
free(copies);
return false;
}
char *map = (char *)vmap;
// upload data
uint32_t buf_off = span.alloc.start + (map - (char *)vmap);
for (int i = 0; i < rects_len; i++) { for (int i = 0; i < rects_len; i++) {
pixman_box32_t rect = rects[i]; pixman_box32_t rect = rects[i];
uint32_t width = rect.x2 - rect.x1; uint32_t width = rect.x2 - rect.x1;
@ -104,22 +126,6 @@ static bool write_pixels(struct wlr_vk_texture *texture,
uint32_t src_y = rect.y1; uint32_t src_y = rect.y1;
uint32_t packed_stride = (uint32_t)pixel_format_info_min_stride(format_info, width); uint32_t packed_stride = (uint32_t)pixel_format_info_min_stride(format_info, width);
// write data into staging buffer span
const char *pdata = vdata; // data iterator
pdata += stride * src_y;
pdata += format_info->bytes_per_block * src_x;
if (src_x == 0 && width == texture->wlr_texture.width &&
stride == packed_stride) {
memcpy(map, pdata, packed_stride * height);
map += packed_stride * height;
} else {
for (unsigned i = 0u; i < height; ++i) {
memcpy(map, pdata, packed_stride);
pdata += stride;
map += packed_stride;
}
}
copies[i] = (VkBufferImageCopy) { copies[i] = (VkBufferImageCopy) {
.imageExtent.width = width, .imageExtent.width = width,
.imageExtent.height = height, .imageExtent.height = height,
@ -136,11 +142,21 @@ static bool write_pixels(struct wlr_vk_texture *texture,
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
}; };
buf_off += height * packed_stride; buf_off += height * packed_stride;
} }
assert((uint32_t)(map - (char *)vmap) == bsize); void *vmap;
res = vkMapMemory(dev, span.buffer->memory, span.alloc.start,
bsize, 0, &vmap);
if (res != VK_SUCCESS) {
wlr_vk_error("vkMapMemory", res);
free(copies);
return false;
}
copy_pixels(vmap, vdata, texture->wlr_texture.width,
stride, bsize, region, format_info);
vkUnmapMemory(dev, span.buffer->memory); vkUnmapMemory(dev, span.buffer->memory);
VkSemaphoreSignalInfoKHR signal_info = { VkSemaphoreSignalInfoKHR signal_info = {