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 "src/gpu/vk/GrVkGpu.h"
9 #include "src/gpu/vk/GrVkUniformBuffer.h"
10 
11 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
12 
Create(GrVkGpu * gpu,size_t size)13 GrVkUniformBuffer* GrVkUniformBuffer::Create(GrVkGpu* gpu, size_t size) {
14     if (0 == size) {
15         return nullptr;
16     }
17     const GrVkResource* resource = nullptr;
18     if (size <= GrVkUniformBuffer::kStandardSize) {
19         resource = gpu->resourceProvider().findOrCreateStandardUniformBufferResource();
20     } else {
21         resource = CreateResource(gpu, size);
22     }
23     if (!resource) {
24         return nullptr;
25     }
26 
27     GrVkBuffer::Desc desc;
28     desc.fDynamic = true;
29     desc.fType = GrVkBuffer::kUniform_Type;
30     desc.fSizeInBytes = size;
31     GrVkUniformBuffer* buffer = new GrVkUniformBuffer(gpu, desc,
32                                                       (const GrVkUniformBuffer::Resource*) resource);
33     if (!buffer) {
34         // this will destroy anything we got from the resource provider,
35         // but this avoids a conditional
36         resource->unref(gpu);
37     }
38     return buffer;
39 }
40 
41 // We implement our own creation function for special buffer resource type
CreateResource(GrVkGpu * gpu,size_t size)42 const GrVkResource* GrVkUniformBuffer::CreateResource(GrVkGpu* gpu, size_t size) {
43     if (0 == size) {
44         return nullptr;
45     }
46 
47     VkBuffer       buffer;
48     GrVkAlloc      alloc;
49 
50     // create the buffer object
51     VkBufferCreateInfo bufInfo;
52     memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
53     bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
54     bufInfo.flags = 0;
55     bufInfo.size = size;
56     bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
57     bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
58     bufInfo.queueFamilyIndexCount = 0;
59     bufInfo.pQueueFamilyIndices = nullptr;
60 
61     VkResult err;
62     err = VK_CALL(gpu, CreateBuffer(gpu->device(), &bufInfo, nullptr, &buffer));
63     if (err) {
64         return nullptr;
65     }
66 
67     if (!GrVkMemory::AllocAndBindBufferMemory(gpu,
68                                               buffer,
69                                               kUniform_Type,
70                                               true,  // dynamic
71                                               &alloc)) {
72         return nullptr;
73     }
74 
75     const GrVkResource* resource = new GrVkUniformBuffer::Resource(buffer, alloc);
76     if (!resource) {
77         VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
78         GrVkMemory::FreeBufferMemory(gpu, kUniform_Type, alloc);
79         return nullptr;
80     }
81 
82     return resource;
83 }
84 
createResource(GrVkGpu * gpu,const GrVkBuffer::Desc & descriptor)85 const GrVkBuffer::Resource* GrVkUniformBuffer::createResource(GrVkGpu* gpu,
86                                                               const GrVkBuffer::Desc& descriptor) {
87     const GrVkResource* vkResource;
88     if (descriptor.fSizeInBytes <= GrVkUniformBuffer::kStandardSize) {
89         GrVkResourceProvider& provider = gpu->resourceProvider();
90         vkResource = provider.findOrCreateStandardUniformBufferResource();
91     } else {
92         vkResource = CreateResource(gpu, descriptor.fSizeInBytes);
93     }
94     return (const GrVkBuffer::Resource*) vkResource;
95 }
96 
onRecycle(GrVkGpu * gpu) const97 void GrVkUniformBuffer::Resource::onRecycle(GrVkGpu* gpu) const {
98     if (fAlloc.fSize <= GrVkUniformBuffer::kStandardSize) {
99         gpu->resourceProvider().recycleStandardUniformBufferResource(this);
100     } else {
101         this->unref(gpu);
102     }
103 }
104