Greg Daniel | 164a9f0 | 2016-02-22 09:56:40 -0500 | [diff] [blame^] | 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 | |