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 "GrVkBuffer.h"
9 #include "GrVkGpu.h"
10 #include "GrVkMemory.h"
11 #include "GrVkUtil.h"
12
13 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
14
15 #ifdef SK_DEBUG
16 #define VALIDATE() this->validate()
17 #else
18 #define VALIDATE() do {} while(false)
19 #endif
20
Create(const GrVkGpu * gpu,const Desc & desc)21 const GrVkBuffer::Resource* GrVkBuffer::Create(const GrVkGpu* gpu, const Desc& desc) {
22 VkBuffer buffer;
23 VkDeviceMemory alloc;
24
25 // create the buffer object
26 VkBufferCreateInfo bufInfo;
27 memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
28 bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
29 bufInfo.flags = 0;
30 bufInfo.size = desc.fSizeInBytes;
31 switch (desc.fType) {
32 case kVertex_Type:
33 bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
34 break;
35 case kIndex_Type:
36 bufInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
37 break;
38 case kUniform_Type:
39 bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
40 break;
41 case kCopyRead_Type:
42 bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
43 break;
44 case kCopyWrite_Type:
45 bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
46 break;
47
48 }
49 bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
50 bufInfo.queueFamilyIndexCount = 0;
51 bufInfo.pQueueFamilyIndices = nullptr;
52
53 VkResult err;
54 err = VK_CALL(gpu, CreateBuffer(gpu->device(), &bufInfo, nullptr, &buffer));
55 if (err) {
56 return nullptr;
57 }
58
59 VkMemoryPropertyFlags requiredMemProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
60 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
61
62 if (!GrVkMemory::AllocAndBindBufferMemory(gpu,
63 buffer,
64 requiredMemProps,
65 &alloc)) {
66 VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
67 return nullptr;
68 }
69
70 const GrVkBuffer::Resource* resource = new GrVkBuffer::Resource(buffer, alloc);
71 if (!resource) {
72 VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
73 VK_CALL(gpu, FreeMemory(gpu->device(), alloc, nullptr));
74 return nullptr;
75 }
76
77 return resource;
78 }
79
80
addMemoryBarrier(const GrVkGpu * gpu,VkAccessFlags srcAccessMask,VkAccessFlags dstAccesMask,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion) const81 void GrVkBuffer::addMemoryBarrier(const GrVkGpu* gpu,
82 VkAccessFlags srcAccessMask,
83 VkAccessFlags dstAccesMask,
84 VkPipelineStageFlags srcStageMask,
85 VkPipelineStageFlags dstStageMask,
86 bool byRegion) const {
87 VkBufferMemoryBarrier bufferMemoryBarrier = {
88 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
89 NULL, // pNext
90 srcAccessMask, // srcAccessMask
91 dstAccesMask, // dstAccessMask
92 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
93 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
94 this->buffer(), // buffer
95 0, // offset
96 fDesc.fSizeInBytes, // size
97 };
98
99 // TODO: restrict to area of buffer we're interested in
100 gpu->addBufferMemoryBarrier(srcStageMask, dstStageMask, byRegion, &bufferMemoryBarrier);
101 }
102
freeGPUData(const GrVkGpu * gpu) const103 void GrVkBuffer::Resource::freeGPUData(const GrVkGpu* gpu) const {
104 SkASSERT(fBuffer);
105 SkASSERT(fAlloc);
106 VK_CALL(gpu, DestroyBuffer(gpu->device(), fBuffer, nullptr));
107 VK_CALL(gpu, FreeMemory(gpu->device(), fAlloc, nullptr));
108 }
109
vkRelease(const GrVkGpu * gpu)110 void GrVkBuffer::vkRelease(const GrVkGpu* gpu) {
111 VALIDATE();
112 fResource->unref(gpu);
113 fResource = nullptr;
114 fMapPtr = nullptr;
115 VALIDATE();
116 }
117
vkAbandon()118 void GrVkBuffer::vkAbandon() {
119 fResource->unrefAndAbandon();
120 fMapPtr = nullptr;
121 VALIDATE();
122 }
123
vkMap(const GrVkGpu * gpu)124 void* GrVkBuffer::vkMap(const GrVkGpu* gpu) {
125 VALIDATE();
126 SkASSERT(!this->vkIsMapped());
127
128 VkResult err = VK_CALL(gpu, MapMemory(gpu->device(), alloc(), 0, VK_WHOLE_SIZE, 0, &fMapPtr));
129 if (err) {
130 fMapPtr = nullptr;
131 }
132
133 VALIDATE();
134 return fMapPtr;
135 }
136
vkUnmap(const GrVkGpu * gpu)137 void GrVkBuffer::vkUnmap(const GrVkGpu* gpu) {
138 VALIDATE();
139 SkASSERT(this->vkIsMapped());
140
141 VK_CALL(gpu, UnmapMemory(gpu->device(), alloc()));
142
143 fMapPtr = nullptr;
144 }
145
vkIsMapped() const146 bool GrVkBuffer::vkIsMapped() const {
147 VALIDATE();
148 return SkToBool(fMapPtr);
149 }
150
vkUpdateData(const GrVkGpu * gpu,const void * src,size_t srcSizeInBytes)151 bool GrVkBuffer::vkUpdateData(const GrVkGpu* gpu, const void* src, size_t srcSizeInBytes) {
152 SkASSERT(!this->vkIsMapped());
153 VALIDATE();
154 if (srcSizeInBytes > fDesc.fSizeInBytes) {
155 return false;
156 }
157
158 void* mapPtr;
159 VkResult err = VK_CALL(gpu, MapMemory(gpu->device(), alloc(), 0, srcSizeInBytes, 0, &mapPtr));
160
161 if (VK_SUCCESS != err) {
162 return false;
163 }
164
165 memcpy(mapPtr, src, srcSizeInBytes);
166
167 VK_CALL(gpu, UnmapMemory(gpu->device(), alloc()));
168
169 return true;
170 }
171
validate() const172 void GrVkBuffer::validate() const {
173 SkASSERT(!fResource || kVertex_Type == fDesc.fType || kIndex_Type == fDesc.fType
174 || kCopyRead_Type == fDesc.fType || kCopyWrite_Type == fDesc.fType
175 || kUniform_Type == fDesc.fType);
176 }
177
178