Advertisement
Guest User

Untitled

a guest
Jun 25th, 2019
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.06 KB | None | 0 0
  1.  
  2. PoolVector<uint8_t> RenderingDeviceVulkan::_texture_get_data_from_image(Texture *tex, VkImage p_image, VmaAllocation p_allocation, uint32_t p_layer) {
  3.  
  4.     uint32_t width, height, depth;
  5.     uint32_t image_size = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps, &width, &height, &depth);
  6.  
  7.     PoolVector<uint8_t> image_data;
  8.     image_data.resize(image_size);
  9.  
  10.     void *img_mem;
  11.     vmaMapMemory(allocator, p_allocation, &img_mem);
  12.  
  13.     uint32_t blockw, blockh;
  14.     get_compressed_image_format_block_dimensions(tex->format, blockw, blockh);
  15.     uint32_t block_size = get_compressed_image_format_block_byte_size(tex->format);
  16.     uint32_t pixel_size = get_image_format_pixel_size(tex->format);
  17.  
  18.     {
  19.         PoolVector<uint8_t>::Write w = image_data.write();
  20.  
  21.         uint32_t mipmap_offset = 0;
  22.         for (uint32_t mm_i = 0; mm_i < tex->mipmaps; mm_i++) {
  23.  
  24.             uint32_t image_total = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, mm_i + 1, &width, &height, &depth);
  25.  
  26.             uint8_t *write_ptr_mipmap = w.ptr() + mipmap_offset;
  27.             image_size = image_total - mipmap_offset;
  28.  
  29.             VkImageSubresource image_sub_resorce;
  30.             image_sub_resorce.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  31.             image_sub_resorce.arrayLayer = p_layer;
  32.             image_sub_resorce.mipLevel = mm_i;
  33.             VkSubresourceLayout layout;
  34.             vkGetImageSubresourceLayout(device, p_image, &image_sub_resorce, &layout);
  35.  
  36.             for (uint32_t z = 0; z < depth; z++) {
  37.                 uint8_t *write_ptr = write_ptr_mipmap + z * image_size / depth;
  38.                 const uint8_t *slice_read_ptr = ((uint8_t *)img_mem) + layout.offset + z * layout.depthPitch;
  39.  
  40.                 if (block_size > 1) {
  41.                     //compressed
  42.                     uint32_t line_width = (block_size * (width / blockw));
  43.                     for (uint32_t y = 0; y < height / blockh; y++) {
  44.                         const uint8_t *rptr = slice_read_ptr + y * layout.rowPitch;
  45.                         uint8_t *wptr = write_ptr + y * line_width;
  46.  
  47.                         copymem(wptr, rptr, line_width);
  48.                     }
  49.  
  50.                 } else {
  51.                     //uncompressed
  52.                     for (uint32_t y = 0; y < height; y++) {
  53.                         const uint8_t *rptr = slice_read_ptr + y * layout.rowPitch;
  54.                         uint8_t *wptr = write_ptr + y * pixel_size * width;
  55.                         copymem(wptr, rptr, pixel_size * width);
  56.                     }
  57.                 }
  58.             }
  59.  
  60.             mipmap_offset = image_total;
  61.         }
  62.     }
  63.  
  64.     vmaUnmapMemory(allocator, p_allocation);
  65.  
  66.     return image_data;
  67. }
  68.  
  69. PoolVector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint32_t p_layer) {
  70.     Texture *tex = texture_owner.getornull(p_texture);
  71.     ERR_FAIL_COND_V(!tex, PoolVector<uint8_t>());
  72.  
  73.     if (tex->bound) {
  74.         ERR_EXPLAIN("Texture can't be retreieved while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
  75.         ERR_FAIL_V(PoolVector<uint8_t>());
  76.     }
  77.  
  78.     if (!(tex->usage_flags & TEXTURE_USAGE_CAN_RETRIEVE_BIT)) {
  79.         ERR_EXPLAIN("Texture requires the TEXTURE_USAGE_CAN_RETRIEVE_BIT in order to be retreieved.");
  80.         ERR_FAIL_V(PoolVector<uint8_t>());
  81.     }
  82.     uint32_t layer_count = tex->layers;
  83.     if (tex->type == TEXTURE_TYPE_CUBE || tex->type == TEXTURE_TYPE_CUBE_ARRAY) {
  84.         layer_count *= 6;
  85.     }
  86.     ERR_FAIL_COND_V(p_layer >= layer_count, PoolVector<uint8_t>());
  87.  
  88.     if (tex->usage_flags & TEXTURE_USAGE_CPU_READ_BIT) {
  89.         //does not need anything fancy, map and read.
  90.         return _texture_get_data_from_image(tex, tex->image, tex->allocation, p_layer);
  91.     } else {
  92.         VkImageCreateInfo image_create_info;
  93.         image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  94.         image_create_info.pNext = NULL;
  95.         image_create_info.flags = 0;
  96.         image_create_info.imageType = vulkan_image_type[tex->type];
  97.         image_create_info.format = vulkan_formats[tex->format];
  98.         image_create_info.extent.width = tex->width;
  99.         image_create_info.extent.height = tex->height;
  100.         image_create_info.extent.depth = tex->depth;
  101.         image_create_info.mipLevels = tex->mipmaps;
  102.         image_create_info.arrayLayers = 1; //for retrieving, only one layer
  103.         image_create_info.samples = rasterization_sample_count[tex->samples];
  104.         image_create_info.tiling = VK_IMAGE_TILING_LINEAR; // for retrieving, linear is recommended
  105.         image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  106.         image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  107.         image_create_info.queueFamilyIndexCount = 0;
  108.         image_create_info.pQueueFamilyIndices = NULL;
  109.         image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  110.  
  111.         VmaAllocationCreateInfo allocInfo;
  112.         allocInfo.flags = 0;
  113.         allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
  114.         allocInfo.requiredFlags = 0;
  115.         allocInfo.preferredFlags = 0;
  116.         allocInfo.memoryTypeBits = 0;
  117.         allocInfo.pool = NULL;
  118.         allocInfo.pUserData = NULL;
  119.  
  120.         VkImage image;
  121.         VmaAllocation allocation;
  122.         VmaAllocationInfo allocation_info;
  123.  
  124.         //Allocate the image
  125.         VkResult err = vmaCreateImage(allocator, &image_create_info, &allocInfo, &image, &allocation, &allocation_info);
  126.         ERR_FAIL_COND_V(err, PoolVector<uint8_t>());
  127.  
  128.         VkCommandBuffer command_buffer = frames[frame].setup_command_buffer;
  129.         //PRE Copy the image
  130.  
  131.         { //Source
  132.             VkImageMemoryBarrier image_memory_barrier;
  133.             image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  134.             image_memory_barrier.pNext = NULL;
  135.             image_memory_barrier.srcAccessMask = 0;
  136.             image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  137.             image_memory_barrier.oldLayout = tex->unbound_layout;
  138.             image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  139.  
  140.             image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  141.             image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  142.             image_memory_barrier.image = tex->image;
  143.             image_memory_barrier.subresourceRange.aspectMask = tex->aspect_mask;
  144.             image_memory_barrier.subresourceRange.baseMipLevel = 0;
  145.             image_memory_barrier.subresourceRange.levelCount = tex->mipmaps;
  146.             image_memory_barrier.subresourceRange.baseArrayLayer = p_layer;
  147.             image_memory_barrier.subresourceRange.layerCount = 1;
  148.  
  149.             vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
  150.         }
  151.         { //Dest
  152.             VkImageMemoryBarrier image_memory_barrier;
  153.             image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  154.             image_memory_barrier.pNext = NULL;
  155.             image_memory_barrier.srcAccessMask = 0;
  156.             image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  157.             image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  158.             image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  159.  
  160.             image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  161.             image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  162.             image_memory_barrier.image = image;
  163.             image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  164.             image_memory_barrier.subresourceRange.baseMipLevel = 0;
  165.             image_memory_barrier.subresourceRange.levelCount = tex->mipmaps;
  166.             image_memory_barrier.subresourceRange.baseArrayLayer = 0;
  167.             image_memory_barrier.subresourceRange.layerCount = 1;
  168.  
  169.             vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
  170.         }
  171.  
  172.         //COPY
  173.  
  174.         {
  175.  
  176.             for (uint32_t i = 0; i < tex->mipmaps; i++) {
  177.  
  178.                 uint32_t mm_width, mm_height, mm_depth;
  179.                 get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, i + 1, &mm_width, &mm_height, &mm_depth);
  180.  
  181.                 VkImageCopy image_copy_region;
  182.                 image_copy_region.srcSubresource.aspectMask = tex->aspect_mask;
  183.                 image_copy_region.srcSubresource.baseArrayLayer = p_layer;
  184.                 image_copy_region.srcSubresource.layerCount = 1;
  185.                 image_copy_region.srcSubresource.mipLevel = i;
  186.                 image_copy_region.srcOffset.x = 0;
  187.                 image_copy_region.srcOffset.y = 0;
  188.                 image_copy_region.srcOffset.z = 0;
  189.  
  190.                 image_copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  191.                 image_copy_region.dstSubresource.baseArrayLayer = p_layer;
  192.                 image_copy_region.dstSubresource.layerCount = 1;
  193.                 image_copy_region.dstSubresource.mipLevel = i;
  194.                 image_copy_region.dstOffset.x = 0;
  195.                 image_copy_region.dstOffset.y = 0;
  196.                 image_copy_region.dstOffset.z = 0;
  197.  
  198.                 image_copy_region.extent.width = mm_width;
  199.                 image_copy_region.extent.height = mm_height;
  200.                 image_copy_region.extent.depth = mm_depth;
  201.  
  202.                 vkCmdCopyImage(command_buffer, tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy_region);
  203.                 print_line("copying mipmap " + itos(i) + " w: " + itos(mm_width) + " h " + itos(mm_height) + " d " + itos(mm_depth));
  204.             }
  205.         }
  206.  
  207.         // RESTORE LAYOUT for SRC and DST
  208.  
  209.         { //restore src
  210.             VkImageMemoryBarrier image_memory_barrier;
  211.             image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  212.             image_memory_barrier.pNext = NULL;
  213.             image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  214.             image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  215.             image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  216.             image_memory_barrier.newLayout = tex->unbound_layout;
  217.             image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  218.             image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  219.             image_memory_barrier.image = tex->image;
  220.             image_memory_barrier.subresourceRange.aspectMask = tex->aspect_mask;
  221.             image_memory_barrier.subresourceRange.baseMipLevel = 0;
  222.             image_memory_barrier.subresourceRange.levelCount = tex->mipmaps;
  223.             image_memory_barrier.subresourceRange.baseArrayLayer = p_layer;
  224.             image_memory_barrier.subresourceRange.layerCount = 1;
  225.  
  226.             vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
  227.         }
  228.  
  229.         { //make dst readable
  230.  
  231.             VkImageMemoryBarrier image_memory_barrier;
  232.             image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  233.             image_memory_barrier.pNext = NULL;
  234.             image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  235.             image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  236.             image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  237.             image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
  238.  
  239.             image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  240.             image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  241.             image_memory_barrier.image = image;
  242.             image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  243.             image_memory_barrier.subresourceRange.baseMipLevel = 0;
  244.             image_memory_barrier.subresourceRange.levelCount = tex->mipmaps;
  245.             image_memory_barrier.subresourceRange.baseArrayLayer = 0;
  246.             image_memory_barrier.subresourceRange.layerCount = 1;
  247.  
  248.             vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
  249.         }
  250.  
  251.         //flush everything so memory can be safely mapped
  252.         _flush(true, false);
  253.  
  254.         PoolVector<uint8_t> ret = _texture_get_data_from_image(tex, image, allocation, p_layer);
  255.         vmaDestroyImage(allocator, image, allocation);
  256.         return ret;
  257.     }
  258. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement