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