| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "GrVkMemory.h" |
| |
| #include "GrVkGpu.h" |
| #include "GrVkUtil.h" |
| |
| static bool get_valid_memory_type_index(VkPhysicalDeviceMemoryProperties physDevMemProps, |
| uint32_t typeBits, |
| VkMemoryPropertyFlags requestedMemFlags, |
| uint32_t* typeIndex) { |
| uint32_t checkBit = 1; |
| for (uint32_t i = 0; i < 32; ++i) { |
| if (typeBits & checkBit) { |
| uint32_t supportedFlags = physDevMemProps.memoryTypes[i].propertyFlags & |
| requestedMemFlags; |
| if (supportedFlags == requestedMemFlags) { |
| *typeIndex = i; |
| return true; |
| } |
| } |
| checkBit <<= 1; |
| } |
| return false; |
| } |
| |
| static bool alloc_device_memory(const GrVkGpu* gpu, |
| VkMemoryRequirements* memReqs, |
| const VkMemoryPropertyFlags flags, |
| VkDeviceMemory* memory) { |
| uint32_t typeIndex; |
| if (!get_valid_memory_type_index(gpu->physicalDeviceMemoryProperties(), |
| memReqs->memoryTypeBits, |
| flags, |
| &typeIndex)) { |
| return false; |
| } |
| |
| VkMemoryAllocateInfo allocInfo = { |
| VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType |
| NULL, // pNext |
| memReqs->size, // allocationSize |
| typeIndex, // memoryTypeIndex |
| }; |
| |
| VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(), |
| &allocInfo, |
| nullptr, |
| memory)); |
| if (err) { |
| return false; |
| } |
| return true; |
| } |
| |
| bool GrVkMemory::AllocAndBindBufferMemory(const GrVkGpu* gpu, |
| VkBuffer buffer, |
| const VkMemoryPropertyFlags flags, |
| VkDeviceMemory* memory) { |
| const GrVkInterface* interface = gpu->vkInterface(); |
| VkDevice device = gpu->device(); |
| |
| VkMemoryRequirements memReqs; |
| GR_VK_CALL(interface, GetBufferMemoryRequirements(device, buffer, &memReqs)); |
| |
| |
| if (!alloc_device_memory(gpu, &memReqs, flags, memory)) { |
| return false; |
| } |
| |
| // Bind Memory to queue |
| VkResult err = GR_VK_CALL(interface, BindBufferMemory(device, buffer, *memory, 0)); |
| if (err) { |
| GR_VK_CALL(interface, FreeMemory(device, *memory, nullptr)); |
| return false; |
| } |
| return true; |
| } |
| |
| bool GrVkMemory::AllocAndBindImageMemory(const GrVkGpu* gpu, |
| VkImage image, |
| const VkMemoryPropertyFlags flags, |
| VkDeviceMemory* memory) { |
| const GrVkInterface* interface = gpu->vkInterface(); |
| VkDevice device = gpu->device(); |
| |
| VkMemoryRequirements memReqs; |
| GR_VK_CALL(interface, GetImageMemoryRequirements(device, image, &memReqs)); |
| |
| if (!alloc_device_memory(gpu, &memReqs, flags, memory)) { |
| return false; |
| } |
| |
| // Bind Memory to queue |
| VkResult err = GR_VK_CALL(interface, BindImageMemory(device, image, *memory, 0)); |
| if (err) { |
| GR_VK_CALL(interface, FreeMemory(device, *memory, nullptr)); |
| return false; |
| } |
| return true; |
| } |
| |
| VkPipelineStageFlags GrVkMemory::LayoutToPipelineStageFlags(const VkImageLayout layout) { |
| if (VK_IMAGE_LAYOUT_GENERAL == layout) { |
| return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; |
| } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout || |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) { |
| return VK_PIPELINE_STAGE_TRANSFER_BIT; |
| } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout || |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout || |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout || |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) { |
| return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; |
| } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) { |
| return VK_PIPELINE_STAGE_HOST_BIT; |
| } |
| |
| SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout); |
| return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; |
| } |
| |
| VkAccessFlags GrVkMemory::LayoutToSrcAccessMask(const VkImageLayout layout) { |
| // Currently we assume we will never being doing any explict shader writes (this doesn't include |
| // color attachment or depth/stencil writes). So we will ignore the |
| // VK_MEMORY_OUTPUT_SHADER_WRITE_BIT. |
| |
| // We can only directly access the host memory if we are in preinitialized or general layout, |
| // and the image is linear. |
| // TODO: Add check for linear here so we are not always adding host to general, and we should |
| // only be in preinitialized if we are linear |
| VkAccessFlags flags = 0;; |
| if (VK_IMAGE_LAYOUT_GENERAL == layout) { |
| flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | |
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | |
| VK_ACCESS_TRANSFER_WRITE_BIT | |
| VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT; |
| } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) { |
| flags = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT; |
| } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) { |
| flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
| } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) { |
| flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; |
| } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) { |
| flags = VK_ACCESS_TRANSFER_WRITE_BIT; |
| } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) { |
| flags = VK_ACCESS_TRANSFER_READ_BIT; |
| } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) { |
| flags = VK_ACCESS_SHADER_READ_BIT; |
| } |
| return flags; |
| } |
| |