Repository: godotengine/godot
File: drivers/vulkan/rendering_device_vulkan.cpp (C++)

Code before:

	for (uint32_t mm_i = 0; mm_i < texture->mipmaps; mm_i++) {
		uint32_t depth;
		uint32_t image_total = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, mm_i + 1, &width, &height, &depth);

		const uint8_t *read_ptr_mipmap = r + mipmap_offset;
		image_size = image_total - mipmap_offset;

		for (uint32_t z = 0; z < depth; z++) { //for 3D textures, depth may be > 0

			const uint8_t *read_ptr = read_ptr_mipmap + image_size * z / depth;

			for (uint32_t x = 0; x < width; x += region_size) {
				for (uint32_t y = 0; y < height; y += region_size) {
					uint32_t region_w = MIN(region_size, width - x);
					uint32_t region_h = MIN(region_size, height - y);

					uint32_t region_logic_w = MIN(region_size, logic_width - x);
					uint32_t region_logic_h = MIN(region_size, logic_height - y);

					uint32_t pixel_size = get_image_format_pixel_size(texture->format);
					uint32_t to_allocate = region_w * region_h * pixel_size;
					to_allocate >>= get_compressed_image_format_pixel_rshift(texture->format);

					uint32_t alloc_offset, alloc_size;
					Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false, !p_use_setup_queue);
					ERR_FAIL_COND_V(err, ERR_CANT_CREATE);

					uint8_t *write_ptr;

					{ //map
						void *data_ptr = nullptr;
						VkResult vkerr = vmaMapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation, &data_ptr);
						ERR_FAIL_COND_V_MSG(vkerr, ERR_CANT_CREATE, "vmaMapMemory failed with error " + itos(vkerr) + ".");
						write_ptr = (uint8_t *)data_ptr;
						write_ptr += alloc_offset;
					}

					uint32_t block_w, block_h;
					get_compressed_image_format_block_dimensions(texture->format, block_w, block_h);

					ERR_FAIL_COND_V(region_w % block_w, ERR_BUG);
					ERR_FAIL_COND_V(region_h % block_h, ERR_BUG);

					if (block_w != 1 || block_h != 1) {
						//compressed image (blocks)
						//must copy a block region

						uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format);
						//re-create current variables in blocky format
						uint32_t xb = x / block_w;

Review comment (suggestion):
This does not look correct to me. If this called from the texture_create function, it needs to use the setup queue. I know moving to dedicated transfer queues will alleviate this, but where not supported this fallback needs to exist.

Code after:
		image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
		image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
		image_memory_barrier.image = texture->image;
		image_memory_barrier.subresourceRange.aspectMask = texture->barrier_aspect_mask;
		image_memory_barrier.subresourceRange.baseMipLevel = 0;
		image_memory_barrier.subresourceRange.levelCount = texture->mipmaps;
		image_memory_barrier.subresourceRange.baseArrayLayer = p_layer;
		image_memory_barrier.subresourceRange.layerCount = 1;

		vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
	}

	uint32_t mipmap_offset = 0;

	uint32_t logic_width = texture->width;
	uint32_t logic_height = texture->height;

	for (uint32_t mm_i = 0; mm_i < texture->mipmaps; mm_i++) {
		uint32_t depth;
		uint32_t image_total = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, mm_i + 1, &width, &height, &depth);

		const uint8_t *read_ptr_mipmap = r + mipmap_offset;
		image_size = image_total - mipmap_offset;

		for (uint32_t z = 0; z < depth; z++) { //for 3D textures, depth may be > 0

			const uint8_t *read_ptr = read_ptr_mipmap + image_size * z / depth;

			for (uint32_t y = 0; y < height; y += region_size) {
				for (uint32_t x = 0; x < width; x += region_size) {
					uint32_t region_w = MIN(region_size, width - x);
					uint32_t region_h = MIN(region_size, height - y);

					uint32_t region_logic_w = MIN(region_size, logic_width - x);
					uint32_t region_logic_h = MIN(region_size, logic_height - y);

					uint32_t pixel_size = get_image_format_pixel_size(texture->format);
					uint32_t to_allocate = region_w * region_h * pixel_size;
					to_allocate >>= get_compressed_image_format_pixel_rshift(texture->format);

					uint32_t alloc_offset, alloc_size;
					Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false);
					ERR_FAIL_COND_V(err, ERR_CANT_CREATE);

					uint8_t *write_ptr;

					{ //map
						void *data_ptr = nullptr;
						VkResult vkerr = vmaMapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation, &data_ptr);
						ERR_FAIL_COND_V_MSG(vkerr, ERR_CANT_CREATE, "vmaMapMemory failed with error " + itos(vkerr) + ".");
						write_ptr = (uint8_t *)data_ptr;