summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-06-11 17:21:39 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 11:53:27 +0100
commit836c2109a0b1371653e3c82100199dfdabd47da9 (patch)
tree9319d8836900a0f4d9e3479de7cf449205377ce7 /drivers
parent3f335ce3d446372eeb9ed87f7e117099c4d2dd6a (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.cpp202
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h4
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;