| /* |
| * 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 "GrVkUniformBuffer.h" |
| #include "GrVkGpu.h" |
| |
| #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) |
| |
| GrVkUniformBuffer* GrVkUniformBuffer::Create(GrVkGpu* gpu, size_t size) { |
| if (0 == size) { |
| return nullptr; |
| } |
| const GrVkResource* resource = nullptr; |
| if (size <= GrVkUniformBuffer::kStandardSize) { |
| resource = gpu->resourceProvider().findOrCreateStandardUniformBufferResource(); |
| } else { |
| resource = CreateResource(gpu, size); |
| } |
| if (!resource) { |
| return nullptr; |
| } |
| |
| GrVkBuffer::Desc desc; |
| desc.fDynamic = true; |
| desc.fType = GrVkBuffer::kUniform_Type; |
| desc.fSizeInBytes = size; |
| GrVkUniformBuffer* buffer = new GrVkUniformBuffer(gpu, desc, |
| (const GrVkUniformBuffer::Resource*) resource); |
| if (!buffer) { |
| // this will destroy anything we got from the resource provider, |
| // but this avoids a conditional |
| resource->unref(gpu); |
| } |
| return buffer; |
| } |
| |
| // We implement our own creation function for special buffer resource type |
| const GrVkResource* GrVkUniformBuffer::CreateResource(GrVkGpu* gpu, size_t size) { |
| if (0 == size) { |
| return nullptr; |
| } |
| |
| VkBuffer buffer; |
| GrVkAlloc alloc; |
| |
| // create the buffer object |
| VkBufferCreateInfo bufInfo; |
| memset(&bufInfo, 0, sizeof(VkBufferCreateInfo)); |
| bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| bufInfo.flags = 0; |
| bufInfo.size = size; |
| bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; |
| bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| bufInfo.queueFamilyIndexCount = 0; |
| bufInfo.pQueueFamilyIndices = nullptr; |
| |
| VkResult err; |
| err = VK_CALL(gpu, CreateBuffer(gpu->device(), &bufInfo, nullptr, &buffer)); |
| if (err) { |
| return nullptr; |
| } |
| |
| if (!GrVkMemory::AllocAndBindBufferMemory(gpu, |
| buffer, |
| kUniform_Type, |
| true, // dynamic |
| &alloc)) { |
| return nullptr; |
| } |
| |
| const GrVkResource* resource = new GrVkUniformBuffer::Resource(buffer, alloc); |
| if (!resource) { |
| VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr)); |
| GrVkMemory::FreeBufferMemory(gpu, kUniform_Type, alloc); |
| return nullptr; |
| } |
| |
| return resource; |
| } |
| |
| const GrVkBuffer::Resource* GrVkUniformBuffer::createResource(GrVkGpu* gpu, |
| const GrVkBuffer::Desc& descriptor) { |
| const GrVkResource* vkResource; |
| if (descriptor.fSizeInBytes <= GrVkUniformBuffer::kStandardSize) { |
| GrVkResourceProvider& provider = gpu->resourceProvider(); |
| vkResource = provider.findOrCreateStandardUniformBufferResource(); |
| } else { |
| vkResource = CreateResource(gpu, descriptor.fSizeInBytes); |
| } |
| return (const GrVkBuffer::Resource*) vkResource; |
| } |
| |
| void GrVkUniformBuffer::Resource::onRecycle(GrVkGpu* gpu) const { |
| if (fAlloc.fSize <= GrVkUniformBuffer::kStandardSize) { |
| gpu->resourceProvider().recycleStandardUniformBufferResource(this); |
| } else { |
| this->unref(gpu); |
| } |
| } |