diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-06-11 17:21:39 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 11:53:27 +0100 |
commit | 836c2109a0b1371653e3c82100199dfdabd47da9 (patch) | |
tree | 9319d8836900a0f4d9e3479de7cf449205377ce7 /drivers | |
parent | 3f335ce3d446372eeb9ed87f7e117099c4d2dd6a (diff) |
Changed my mind on Vulkan image API, images should now include mipmaps
This should make it easier to obtain the data directly from an Image
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.cpp | 202 | ||||
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.h | 4 |
2 files changed, 104 insertions, 102 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 6466c8a19b..7e9d40df19 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1010,7 +1010,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_pixel_rshift(DataFor return 0; } -uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmap, uint32_t *r_blockw, uint32_t *r_blockh) { +uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmaps, uint32_t *r_blockw, uint32_t *r_blockh) { uint32_t w = p_width; uint32_t h = p_height; @@ -1023,7 +1023,7 @@ uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_form uint32_t blockw, blockh; get_compressed_image_format_block_dimensions(p_format, blockw, blockh); - for (uint32_t i = 0; i <= p_mipmap; i++) { + for (uint32_t i = 0; i <= p_mipmaps; i++) { uint32_t bw = w % blockw != 0 ? w + (blockw - w % blockw) : w; uint32_t bh = h % blockh != 0 ? h + (blockh - h % blockh) : h; @@ -1032,7 +1032,7 @@ uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_form s *= pixel_size; s >>= pixel_rshift; - size = s * d; + size += s * d; if (r_blockw) { *r_blockw = bw; } @@ -1565,19 +1565,14 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T ERR_FAIL_COND_V_MSG(!(p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT), RID(), "Texture needs the TEXTURE_USAGE_CAN_UPDATE_BIT usage flag in order to be updated at initialization or later"); - int expected_images = image_create_info.mipLevels * image_create_info.arrayLayers * array_layer_multiplier; + int expected_images = image_create_info.arrayLayers * array_layer_multiplier; ERR_FAIL_COND_V_MSG(p_data.size() != expected_images, RID(), "Default supplied data for image format is of invalid length (" + itos(p_data.size()) + "), should be (" + itos(expected_images) + ")."); - int idx = 0; for (uint32_t i = 0; i < image_create_info.arrayLayers * array_layer_multiplier; i++) { - for (uint32_t j = 0; j < image_create_info.mipLevels; j++) { - print_line("computed size from " + Vector3(image_create_info.extent.width, image_create_info.extent.height, image_create_info.extent.depth)); - uint32_t required_size = get_image_format_required_size(p_format.format, image_create_info.extent.width, image_create_info.extent.height, image_create_info.extent.depth, j); - ERR_FAIL_COND_V_MSG((uint32_t)p_data[idx].size() != required_size, RID(), - "Data for slice index " + itos(idx) + " (mapped to layer " + itos(i) + ", mipmap " + itos(j) + ") differs in size (supplied: " + itos(p_data[idx].size()) + ") than what is required by the format (" + itos(required_size) + ")."); - idx++; - } + uint32_t required_size = get_image_format_required_size(p_format.format, image_create_info.extent.width, image_create_info.extent.height, image_create_info.extent.depth, image_create_info.mipLevels); + ERR_FAIL_COND_V_MSG((uint32_t)p_data[i].size() != required_size, RID(), + "Data for slice index " + itos(i) + " (mapped to layer " + itos(i) + ") differs in size (supplied: " + itos(p_data[i].size()) + ") than what is required by the format (" + itos(required_size) + ")."); } } @@ -1765,9 +1760,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T if (p_data.size()) { for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) { - for (uint32_t j = 0; j < image_create_info.mipLevels; j++) { - texture_update(id, j, i, p_data[i * image_create_info.mipLevels + j], true); - } + texture_update(id, i, p_data[i], true); } } return id; @@ -1856,7 +1849,7 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID return id; } -Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_mipmap, uint32_t p_layer, const PoolVector<uint8_t> &p_data, bool p_sync_with_draw) { +Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const PoolVector<uint8_t> &p_data, bool p_sync_with_draw) { _THREAD_SAFE_METHOD_ @@ -1875,7 +1868,6 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_mipmap, ui ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_CAN_UPDATE_BIT), ERR_INVALID_PARAMETER, "Texture requires the TEXTURE_USAGE_CAN_UPDATE_BIT in order to be updatable."); - ERR_FAIL_COND_V(p_mipmap >= texture->mipmaps, ERR_INVALID_PARAMETER); uint32_t layer_count = texture->layers; if (texture->type == TEXTURE_TYPE_CUBE || texture->type == TEXTURE_TYPE_CUBE_ARRAY) { layer_count *= 6; @@ -1883,7 +1875,7 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_mipmap, ui ERR_FAIL_COND_V(p_layer >= layer_count, ERR_INVALID_PARAMETER); uint32_t width, height; - uint32_t image_size = get_image_format_required_size(texture->format, texture->width, texture->height, 1, p_mipmap, &width, &height); + uint32_t image_size = get_image_format_required_size(texture->format, texture->width, texture->height, 1, texture->mipmaps, &width, &height); uint32_t required_size = image_size * texture->depth; ERR_FAIL_COND_V_MSG(required_size != (uint32_t)p_data.size(), ERR_INVALID_PARAMETER, @@ -1909,118 +1901,128 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_mipmap, ui image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.image = texture->image; image_memory_barrier.subresourceRange.aspectMask = texture->aspect_mask; - image_memory_barrier.subresourceRange.baseMipLevel = p_mipmap; - image_memory_barrier.subresourceRange.levelCount = 1; + 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_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier); } - for (uint32_t z = 0; z < texture->depth; z++) { //for 3D textures, depth may be > 0 + uint32_t mipmap_offset = 0; + for (uint32_t mm_i = 0; mm_i < texture->mipmaps; mm_i++) { - const uint8_t *read_ptr = r.ptr(); - read_ptr += image_size * z; + uint32_t image_total = get_image_format_required_size(texture->format, texture->width, texture->height, 1, mm_i + 1, &width, &height); - for (uint32_t x = 0; x < width; x += region_size) { - for (uint32_t y = 0; y < height; y += region_size) { + const uint8_t *read_ptr = r.ptr() + mipmap_offset; + image_size = image_total - mipmap_offset; - uint32_t region_w = MIN(region_size, width - x); - uint32_t region_h = MIN(region_size, height - y); + for (uint32_t z = 0; z < texture->depth; z++) { //for 3D textures, depth may be > 0 - 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); + read_ptr += image_size; - uint32_t alloc_offset, alloc_size; - Error err = _staging_buffer_allocate(to_allocate, 32, alloc_offset, alloc_size, false, p_sync_with_draw); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + 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); - uint8_t *write_ptr; + 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); - { //map - void *data_ptr = NULL; - VkResult vkerr = vmaMapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation, &data_ptr); - if (vkerr) { - ERR_FAIL_V(ERR_CANT_CREATE); + uint32_t alloc_offset, alloc_size; + Error err = _staging_buffer_allocate(to_allocate, 32, alloc_offset, alloc_size, false, p_sync_with_draw); + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + + uint8_t *write_ptr; + + { //map + void *data_ptr = NULL; + VkResult vkerr = vmaMapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation, &data_ptr); + if (vkerr) { + ERR_FAIL_V(ERR_CANT_CREATE); + } + write_ptr = (uint8_t *)data_ptr; + write_ptr += alloc_offset; } - 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; - uint32_t yb = y / block_h; - uint32_t wb = width / block_w; - //uint32_t hb = height / block_h; - uint32_t region_wb = region_w / block_w; - uint32_t region_hb = region_h / block_h; - for (uint32_t xr = 0; xr < region_wb; xr++) { - for (uint32_t yr = 0; yr < region_hb; yr++) { - uint32_t src_offset = ((yr + yb) * wb + xr + xb) * block_size; - uint32_t dst_offset = (yr * region_wb + xr) * block_size; - //copy block - for (uint32_t i = 0; i < block_size; i++) { - write_ptr[dst_offset + i] = read_ptr[src_offset + i]; + 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; + uint32_t yb = y / block_h; + uint32_t wb = width / block_w; + //uint32_t hb = height / block_h; + uint32_t region_wb = region_w / block_w; + uint32_t region_hb = region_h / block_h; + for (uint32_t xr = 0; xr < region_wb; xr++) { + for (uint32_t yr = 0; yr < region_hb; yr++) { + uint32_t src_offset = ((yr + yb) * wb + xr + xb) * block_size; + uint32_t dst_offset = (yr * region_wb + xr) * block_size; + //copy block + for (uint32_t i = 0; i < block_size; i++) { + write_ptr[dst_offset + i] = read_ptr[src_offset + i]; + } } } - } - } else { - //regular image (pixels) - //must copy a pixel region + } else { + //regular image (pixels) + //must copy a pixel region - for (uint32_t xr = 0; xr < region_w; xr++) { - for (uint32_t yr = 0; yr < region_h; yr++) { - uint32_t src_offset = ((yr + y) * width + xr + x) * pixel_size; - uint32_t dst_offset = (yr * region_w + xr) * pixel_size; - //copy block - for (uint32_t i = 0; i < pixel_size; i++) { + for (uint32_t xr = 0; xr < region_w; xr++) { + for (uint32_t yr = 0; yr < region_h; yr++) { + uint32_t src_offset = ((yr + y) * width + xr + x) * pixel_size; + uint32_t dst_offset = (yr * region_w + xr) * pixel_size; + //copy block + for (uint32_t i = 0; i < pixel_size; i++) { - write_ptr[dst_offset + i] = read_ptr[src_offset + i]; + write_ptr[dst_offset + i] = read_ptr[src_offset + i]; + } } } } - } - { //unmap - vmaUnmapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation); - } + { //unmap + vmaUnmapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation); + } - VkBufferImageCopy buffer_image_copy; - buffer_image_copy.bufferOffset = alloc_offset; - buffer_image_copy.bufferRowLength = 0; //tigthly packed - buffer_image_copy.bufferImageHeight = 0; //tigthly packed + VkBufferImageCopy buffer_image_copy; + buffer_image_copy.bufferOffset = alloc_offset; + buffer_image_copy.bufferRowLength = 0; //tigthly packed + buffer_image_copy.bufferImageHeight = 0; //tigthly packed - buffer_image_copy.imageSubresource.aspectMask = texture->aspect_mask; - buffer_image_copy.imageSubresource.baseArrayLayer = p_layer; - buffer_image_copy.imageSubresource.mipLevel = p_mipmap; - buffer_image_copy.imageSubresource.layerCount = 1; + buffer_image_copy.imageSubresource.aspectMask = texture->aspect_mask; + buffer_image_copy.imageSubresource.mipLevel = mm_i; + buffer_image_copy.imageSubresource.baseArrayLayer = p_layer; + buffer_image_copy.imageSubresource.layerCount = 1; - buffer_image_copy.imageOffset.x = x; - buffer_image_copy.imageOffset.y = y; - buffer_image_copy.imageOffset.z = z; + buffer_image_copy.imageOffset.x = x; + buffer_image_copy.imageOffset.y = y; + buffer_image_copy.imageOffset.z = z; - buffer_image_copy.imageExtent.width = region_w; - buffer_image_copy.imageExtent.height = region_h; - buffer_image_copy.imageExtent.depth = 1; + buffer_image_copy.imageExtent.width = region_w; + buffer_image_copy.imageExtent.height = region_h; + buffer_image_copy.imageExtent.depth = 1; - vkCmdCopyBufferToImage(command_buffer, staging_buffer_blocks[staging_buffer_current].buffer, texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy); + vkCmdCopyBufferToImage(command_buffer, staging_buffer_blocks[staging_buffer_current].buffer, texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy); - staging_buffer_blocks.write[staging_buffer_current].fill_amount += alloc_size; + staging_buffer_blocks.write[staging_buffer_current].fill_amount += alloc_size; + } } } + + mipmap_offset = image_total; } //barrier to restore layout @@ -2036,8 +2038,8 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_mipmap, ui image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; image_memory_barrier.image = texture->image; image_memory_barrier.subresourceRange.aspectMask = texture->aspect_mask; - image_memory_barrier.subresourceRange.baseMipLevel = p_mipmap; - image_memory_barrier.subresourceRange.levelCount = 1; + 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; diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 492b1c7509..dd908df8f0 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -44,7 +44,7 @@ class RenderingDeviceVulkan : public RenderingDevice { static void get_compressed_image_format_block_dimensions(DataFormat p_format, uint32_t &r_w, uint32_t &r_h); uint32_t get_compressed_image_format_block_byte_size(DataFormat p_format); static uint32_t get_compressed_image_format_pixel_rshift(DataFormat p_format); - static uint32_t get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmap, uint32_t *r_blockw = NULL, uint32_t *r_blockh = NULL); + static uint32_t get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmaps, uint32_t *r_blockw = NULL, uint32_t *r_blockh = NULL); static uint32_t get_image_required_mipmaps(uint32_t p_width, uint32_t p_height, uint32_t p_depth); /***************************/ @@ -678,7 +678,7 @@ class RenderingDeviceVulkan : public RenderingDevice { public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<PoolVector<uint8_t> > &p_data = Vector<PoolVector<uint8_t> >()); virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture); - virtual Error texture_update(RID p_texture, uint32_t p_mipmap, uint32_t p_layer, const PoolVector<uint8_t> &p_data, bool p_sync_with_draw = false); + virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector<uint8_t> &p_data, bool p_sync_with_draw = false); virtual bool texture_is_format_supported_for_usage(DataFormat p_format, TextureUsageBits p_usage) const; |