• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_valid_memory_type_index(VkPhysicalDeviceMemoryProperties physDevMemProps,uint32_t typeBits,VkMemoryPropertyFlags requestedMemFlags,uint32_t * typeIndex)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 
alloc_device_memory(const GrVkGpu * gpu,VkMemoryRequirements * memReqs,const VkMemoryPropertyFlags flags,VkDeviceMemory * memory)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 
AllocAndBindBufferMemory(const GrVkGpu * gpu,VkBuffer buffer,const VkMemoryPropertyFlags flags,VkDeviceMemory * memory)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 
AllocAndBindImageMemory(const GrVkGpu * gpu,VkImage image,const VkMemoryPropertyFlags flags,VkDeviceMemory * memory)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 
LayoutToPipelineStageFlags(const VkImageLayout layout)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 
LayoutToSrcAccessMask(const VkImageLayout layout)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