Home | History | Annotate | Download | only in vk
      1 /*
      2 * Copyright 2015 Google Inc.
      3 *
      4 * Use of this source code is governed by a BSD-style license that can be
      5 * found in the LICENSE file.
      6 */
      7 
      8 #include "GrVkMemory.h"
      9 
     10 #include "GrVkGpu.h"
     11 #include "GrVkUtil.h"
     12 
     13 static bool get_valid_memory_type_index(VkPhysicalDeviceMemoryProperties physDevMemProps,
     14                                         uint32_t typeBits,
     15                                         VkMemoryPropertyFlags requestedMemFlags,
     16                                         uint32_t* typeIndex) {
     17     uint32_t checkBit = 1;
     18     for (uint32_t i = 0; i < 32; ++i) {
     19         if (typeBits & checkBit) {
     20             uint32_t supportedFlags = physDevMemProps.memoryTypes[i].propertyFlags &
     21                                       requestedMemFlags;
     22             if (supportedFlags == requestedMemFlags) {
     23                 *typeIndex = i;
     24                 return true;
     25             }
     26         }
     27         checkBit <<= 1;
     28     }
     29     return false;
     30 }
     31 
     32 static bool alloc_device_memory(const GrVkGpu* gpu,
     33                                 VkMemoryRequirements* memReqs,
     34                                 const VkMemoryPropertyFlags flags,
     35                                 VkDeviceMemory* memory) {
     36     uint32_t typeIndex;
     37     if (!get_valid_memory_type_index(gpu->physicalDeviceMemoryProperties(),
     38                                      memReqs->memoryTypeBits,
     39                                      flags,
     40                                      &typeIndex)) {
     41         return false;
     42     }
     43 
     44     VkMemoryAllocateInfo allocInfo = {
     45         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
     46         NULL,                                        // pNext
     47         memReqs->size,                               // allocationSize
     48         typeIndex,                                   // memoryTypeIndex
     49     };
     50 
     51     VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(),
     52                                                                  &allocInfo,
     53                                                                  nullptr,
     54                                                                  memory));
     55     if (err) {
     56         return false;
     57     }
     58     return true;
     59 }
     60 
     61 bool GrVkMemory::AllocAndBindBufferMemory(const GrVkGpu* gpu,
     62                                           VkBuffer buffer,
     63                                           const VkMemoryPropertyFlags flags,
     64                                           VkDeviceMemory* memory) {
     65     const GrVkInterface* interface = gpu->vkInterface();
     66     VkDevice device = gpu->device();
     67 
     68     VkMemoryRequirements memReqs;
     69     GR_VK_CALL(interface, GetBufferMemoryRequirements(device, buffer, &memReqs));
     70 
     71 
     72     if (!alloc_device_memory(gpu, &memReqs, flags, memory)) {
     73         return false;
     74     }
     75 
     76     // Bind Memory to queue
     77     VkResult err = GR_VK_CALL(interface, BindBufferMemory(device, buffer, *memory, 0));
     78     if (err) {
     79         GR_VK_CALL(interface, FreeMemory(device, *memory, nullptr));
     80         return false;
     81     }
     82     return true;
     83 }
     84 
     85 bool GrVkMemory::AllocAndBindImageMemory(const GrVkGpu* gpu,
     86                                          VkImage image,
     87                                          const VkMemoryPropertyFlags flags,
     88                                          VkDeviceMemory* memory) {
     89     const GrVkInterface* interface = gpu->vkInterface();
     90     VkDevice device = gpu->device();
     91 
     92     VkMemoryRequirements memReqs;
     93     GR_VK_CALL(interface, GetImageMemoryRequirements(device, image, &memReqs));
     94 
     95     if (!alloc_device_memory(gpu, &memReqs, flags, memory)) {
     96         return false;
     97     }
     98 
     99     // Bind Memory to queue
    100     VkResult err = GR_VK_CALL(interface, BindImageMemory(device, image, *memory, 0));
    101     if (err) {
    102         GR_VK_CALL(interface, FreeMemory(device, *memory, nullptr));
    103         return false;
    104     }
    105     return true;
    106 }
    107 
    108 VkPipelineStageFlags GrVkMemory::LayoutToPipelineStageFlags(const VkImageLayout layout) {
    109     if (VK_IMAGE_LAYOUT_GENERAL == layout) {
    110         return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    111     } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
    112                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
    113         return VK_PIPELINE_STAGE_TRANSFER_BIT;
    114     } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout ||
    115                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout ||
    116                VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout ||
    117                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
    118         return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    119     } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
    120         return VK_PIPELINE_STAGE_HOST_BIT;
    121     }
    122 
    123     SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout);
    124     return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    125 }
    126 
    127 VkAccessFlags GrVkMemory::LayoutToSrcAccessMask(const VkImageLayout layout) {
    128     // Currently we assume we will never being doing any explict shader writes (this doesn't include
    129     // color attachment or depth/stencil writes). So we will ignore the
    130     // VK_MEMORY_OUTPUT_SHADER_WRITE_BIT.
    131 
    132     // We can only directly access the host memory if we are in preinitialized or general layout,
    133     // and the image is linear.
    134     // TODO: Add check for linear here so we are not always adding host to general, and we should
    135     //       only be in preinitialized if we are linear
    136     VkAccessFlags flags = 0;;
    137     if (VK_IMAGE_LAYOUT_GENERAL == layout) {
    138         flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
    139             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
    140             VK_ACCESS_TRANSFER_WRITE_BIT |
    141             VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT;
    142     } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
    143         flags = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT;
    144     } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
    145         flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    146     } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) {
    147         flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    148     } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
    149         flags = VK_ACCESS_TRANSFER_WRITE_BIT;
    150     } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) {
    151         flags = VK_ACCESS_TRANSFER_READ_BIT;
    152     } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
    153         flags = VK_ACCESS_SHADER_READ_BIT;
    154     }
    155     return flags;
    156 }
    157 
    158