From: Bas Nieuwenhuizen <ba...@chromium.org> We basically split the loop so we create the images before allocation, as well pass on the pitch to the cru_images for the comparison. --- src/tests/func/miptree/miptree.c | 181 ++++++++++++++++++++++++++++----------- 1 file changed, 130 insertions(+), 51 deletions(-)
diff --git a/src/tests/func/miptree/miptree.c b/src/tests/func/miptree/miptree.c index b9a73c5..0fe989e 100644 --- a/src/tests/func/miptree/miptree.c +++ b/src/tests/func/miptree/miptree.c @@ -114,7 +114,8 @@ struct mipslice { uint32_t height; uint32_t depth; - uint32_t buffer_offset; + uint32_t src_buffer_offset; + uint32_t dst_buffer_offset; VkImage src_vk_image; VkImage dest_vk_image; @@ -505,42 +506,14 @@ miptree_create(void) }, .tiling = VK_IMAGE_TILING_OPTIMAL, .usage = usage_bits); - VkBuffer src_buffer = qoCreateBuffer(t_device, - .size = buffer_size, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT); - VkBuffer dest_buffer = qoCreateBuffer(t_device, - .size = buffer_size, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT); - - VkDeviceMemory image_mem = qoAllocImageMemory(t_device, image, - .properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VkDeviceMemory src_buffer_mem = qoAllocBufferMemory(t_device, src_buffer, - .properties = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - VkDeviceMemory dest_buffer_mem = qoAllocBufferMemory(t_device, dest_buffer, - .properties = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - void *src_buffer_map = qoMapMemory(t_device, src_buffer_mem, - /*offset*/ 0, buffer_size, 0); - void *dest_buffer_map = qoMapMemory(t_device, dest_buffer_mem, - /*offset*/ 0, buffer_size, 0); - qoBindImageMemory(t_device, image, image_mem, /*offset*/ 0); - qoBindBufferMemory(t_device, src_buffer, src_buffer_mem, /*offset*/ 0); - qoBindBufferMemory(t_device, dest_buffer, dest_buffer_mem, /*offset*/ 0); - - miptree_t *mt = xzalloc(sizeof(*mt)); - t_cleanup_push_callback((cru_cleanup_callback_func_t) miptree_destroy, mt); - - mt->image = image; - mt->src_buffer = src_buffer; - mt->dest_buffer = dest_buffer; - mt->width = width; - mt->height = height; - mt->levels = levels; - mt->array_length = array_length; - cru_vec_init(&mt->mipslices); - - uint32_t buffer_offset = 0; + uint32_t src_buffer_offset = 0; + uint32_t dst_buffer_offset = 0; + VkImage src_images[levels * MAX(depth, array_length)]; + VkImage dst_images[levels * MAX(depth, array_length)]; + uint32_t src_buffer_offsets[levels * MAX(depth, array_length)]; + uint32_t dst_buffer_offsets[levels * MAX(depth, array_length)]; + unsigned image_idx = 0; for (uint32_t l = 0; l < levels; ++l) { const uint32_t level_width = cru_minify(width, l); @@ -553,9 +526,6 @@ miptree_create(void) const uint32_t num_layers = MAX(level_depth, array_length); for (uint32_t layer = 0; layer < num_layers; ++layer) { - void *src_pixels = src_buffer_map + buffer_offset; - void *dest_pixels = dest_buffer_map + buffer_offset; - uint32_t src_usage, dest_usage; VkFormat dest_format; VkImage src_vk_image; @@ -593,8 +563,6 @@ miptree_create(void) }, .tiling = VK_IMAGE_TILING_LINEAR, .usage = src_usage); - qoBindImageMemory(t_device, src_vk_image, src_buffer_mem, - buffer_offset); break; } @@ -632,11 +600,121 @@ miptree_create(void) }, .tiling = VK_IMAGE_TILING_LINEAR, .usage = dest_usage); - qoBindImageMemory(t_device, dest_vk_image, dest_buffer_mem, - buffer_offset); break; } + if (src_vk_image) { + VkMemoryRequirements requirements; + requirements = qoGetImageMemoryRequirements(t_device, src_vk_image); + src_buffer_offset = (src_buffer_offset + requirements.alignment - 1) / requirements.alignment * requirements.alignment; + src_buffer_offsets[image_idx] = src_buffer_offset; + src_buffer_offset += requirements.size; + } else { + src_buffer_offsets[image_idx] = src_buffer_offset; + src_buffer_offset += cpp * level_width * level_height; + } + + if (dest_vk_image) { + VkMemoryRequirements requirements; + requirements = qoGetImageMemoryRequirements(t_device, dest_vk_image); + dst_buffer_offset = (dst_buffer_offset + requirements.alignment - 1) / requirements.alignment * requirements.alignment; + dst_buffer_offsets[image_idx] = dst_buffer_offset; + dst_buffer_offset += requirements.size; + } else { + dst_buffer_offsets[image_idx] = dst_buffer_offset; + dst_buffer_offset += cpp * level_width * level_height; + } + + src_images[image_idx] = src_vk_image; + dst_images[image_idx] = dest_vk_image; + ++image_idx; + } + } + + const uint32_t src_buffer_size = MAX(buffer_size, src_buffer_offset); + const uint32_t dst_buffer_size = MAX(buffer_size, dst_buffer_offset); + + VkBuffer src_buffer = qoCreateBuffer(t_device, + .size = src_buffer_size, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + VkBuffer dest_buffer = qoCreateBuffer(t_device, + .size = dst_buffer_size, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + + /* TODO: make sure these are allowed in the image memory requirements. */ + VkDeviceMemory image_mem = qoAllocImageMemory(t_device, image, + .properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VkDeviceMemory src_buffer_mem = qoAllocBufferMemory(t_device, src_buffer, + .properties = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + VkDeviceMemory dest_buffer_mem = qoAllocBufferMemory(t_device, dest_buffer, + .properties = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + void *src_buffer_map = qoMapMemory(t_device, src_buffer_mem, + /*offset*/ 0, buffer_size, 0); + void *dest_buffer_map = qoMapMemory(t_device, dest_buffer_mem, + /*offset*/ 0, buffer_size, 0); + + qoBindImageMemory(t_device, image, image_mem, /*offset*/ 0); + qoBindBufferMemory(t_device, src_buffer, src_buffer_mem, /*offset*/ 0); + qoBindBufferMemory(t_device, dest_buffer, dest_buffer_mem, /*offset*/ 0); + + miptree_t *mt = xzalloc(sizeof(*mt)); + t_cleanup_push_callback((cru_cleanup_callback_func_t) miptree_destroy, mt); + + mt->image = image; + mt->src_buffer = src_buffer; + mt->dest_buffer = dest_buffer; + mt->width = width; + mt->height = height; + mt->levels = levels; + mt->array_length = array_length; + cru_vec_init(&mt->mipslices); + + image_idx = 0; + + for (uint32_t l = 0; l < levels; ++l) { + const uint32_t level_width = cru_minify(width, l); + const uint32_t level_height = cru_minify(height, l); + const uint32_t level_depth = cru_minify(depth, l); + + // 3D array textures are illegal. + t_assert(level_depth == 1 || array_length == 1); + + const uint32_t num_layers = MAX(level_depth, array_length); + + for (uint32_t layer = 0; layer < num_layers; ++layer) { + const VkImage src_vk_image = src_images[image_idx]; + const VkImage dest_vk_image = dst_images[image_idx]; + uint32_t src_offset = src_buffer_offsets[image_idx]; + uint32_t dst_offset = dst_buffer_offsets[image_idx]; + uint32_t src_stride = 0, dst_stride = 0; + const VkImageSubresource subresource = (VkImageSubresource){ + .aspectMask = params->aspect, + .mipLevel = 0, + .arrayLayer = 0, + }; + + if (src_vk_image) { + qoBindImageMemory(t_device, src_vk_image, src_buffer_mem, + src_buffer_offsets[image_idx]); + + VkSubresourceLayout layout = qoGetImageSubresourceLayout(t_device, src_vk_image, &subresource); + src_offset += layout.offset; + src_stride = layout.rowPitch; + } + + if (dest_vk_image) { + qoBindImageMemory(t_device, dest_vk_image, dest_buffer_mem, + dst_buffer_offsets[image_idx]); + + VkSubresourceLayout layout = qoGetImageSubresourceLayout(t_device, dest_vk_image, &subresource); + dst_offset += layout.offset; + dst_stride = layout.rowPitch; + } + + void *src_pixels = src_buffer_map + src_offset; + void *dest_pixels = dest_buffer_map + dst_offset; + cru_image_t *templ_image; cru_image_t *src_image; cru_image_t *dest_image; @@ -648,16 +726,16 @@ miptree_create(void) t_assert(level_width == cru_image_get_width(templ_image)); t_assert(level_height == cru_image_get_height(templ_image)); - src_image = t_new_cru_image_from_pixels(src_pixels, - format, level_width, level_height); + src_image = t_new_cru_image_from_pixels_with_stride(src_pixels, + format, level_width, level_height, src_stride); t_assert(cru_image_copy(src_image, templ_image)); mipslice_perturb_pixels(src_pixels, format_info, level_width, level_height, l, levels, layer, num_layers); - dest_image = t_new_cru_image_from_pixels(dest_pixels, - format, level_width, level_height); + dest_image = t_new_cru_image_from_pixels_with_stride(dest_pixels, + format, level_width, level_height, dst_stride); fill_rect_with_canary(dest_pixels, format_info, level_width, level_height); @@ -678,7 +756,8 @@ miptree_create(void) .height = level_height, .depth = level_depth, - .buffer_offset = buffer_offset, + .src_buffer_offset = src_offset, + .dst_buffer_offset = dst_offset, .src_vk_image = src_vk_image, .dest_vk_image = dest_vk_image, @@ -689,7 +768,7 @@ miptree_create(void) cru_vec_push_memcpy(&mt->mipslices, &mipslice, 1); - buffer_offset += cpp * level_width * level_height; + ++image_idx; } } @@ -726,7 +805,7 @@ miptree_upload_copy_from_buffer(const test_data_t *data) }); cru_vec_foreach(slice, &mt->mipslices) { VkBufferImageCopy copy = { - .bufferOffset = slice->buffer_offset, + .bufferOffset = slice->src_buffer_offset, .imageSubresource = { .aspectMask = params->aspect, .mipLevel = slice->level, @@ -765,7 +844,7 @@ miptree_download_copy_to_buffer(const test_data_t *data) cru_vec_foreach(slice, &mt->mipslices) { VkBufferImageCopy copy = { - .bufferOffset = slice->buffer_offset, + .bufferOffset = slice->dst_buffer_offset, .imageSubresource = { .aspectMask = params->aspect, .mipLevel = slice->level, -- 2.16.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev