123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /*
- * 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 "src/gpu/vk/GrVkBuffer.h"
- #include "src/gpu/vk/GrVkGpu.h"
- #include "src/gpu/vk/GrVkMemory.h"
- #include "src/gpu/vk/GrVkTransferBuffer.h"
- #include "src/gpu/vk/GrVkUtil.h"
- #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
- #ifdef SK_DEBUG
- #define VALIDATE() this->validate()
- #else
- #define VALIDATE() do {} while(false)
- #endif
- const GrVkBuffer::Resource* GrVkBuffer::Create(const GrVkGpu* gpu, const Desc& desc) {
- SkASSERT(!gpu->protectedContext() || (gpu->protectedContext() == desc.fDynamic));
- 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 = desc.fSizeInBytes;
- switch (desc.fType) {
- case kVertex_Type:
- bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- break;
- case kIndex_Type:
- bufInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
- break;
- case kUniform_Type:
- bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
- break;
- case kCopyRead_Type:
- bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- break;
- case kCopyWrite_Type:
- bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case kTexel_Type:
- bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
- }
- if (!desc.fDynamic) {
- bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_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,
- desc.fType,
- desc.fDynamic,
- &alloc)) {
- return nullptr;
- }
- const GrVkBuffer::Resource* resource = new GrVkBuffer::Resource(buffer, alloc, desc.fType);
- if (!resource) {
- VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
- GrVkMemory::FreeBufferMemory(gpu, desc.fType, alloc);
- return nullptr;
- }
- return resource;
- }
- void GrVkBuffer::addMemoryBarrier(const GrVkGpu* gpu,
- VkAccessFlags srcAccessMask,
- VkAccessFlags dstAccesMask,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- bool byRegion) const {
- VkBufferMemoryBarrier bufferMemoryBarrier = {
- VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
- nullptr, // pNext
- srcAccessMask, // srcAccessMask
- dstAccesMask, // dstAccessMask
- VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
- VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
- this->buffer(), // buffer
- 0, // offset
- fDesc.fSizeInBytes, // size
- };
- // TODO: restrict to area of buffer we're interested in
- gpu->addBufferMemoryBarrier(this->resource(), srcStageMask, dstStageMask, byRegion,
- &bufferMemoryBarrier);
- }
- void GrVkBuffer::Resource::freeGPUData(GrVkGpu* gpu) const {
- SkASSERT(fBuffer);
- SkASSERT(fAlloc.fMemory);
- VK_CALL(gpu, DestroyBuffer(gpu->device(), fBuffer, nullptr));
- GrVkMemory::FreeBufferMemory(gpu, fType, fAlloc);
- }
- void GrVkBuffer::vkRelease(const GrVkGpu* gpu) {
- VALIDATE();
- fResource->recycle(const_cast<GrVkGpu*>(gpu));
- fResource = nullptr;
- if (!fDesc.fDynamic) {
- delete[] (unsigned char*)fMapPtr;
- }
- fMapPtr = nullptr;
- VALIDATE();
- }
- void GrVkBuffer::vkAbandon() {
- fResource->unrefAndAbandon();
- fResource = nullptr;
- if (!fDesc.fDynamic) {
- delete[] (unsigned char*)fMapPtr;
- }
- fMapPtr = nullptr;
- VALIDATE();
- }
- VkAccessFlags buffer_type_to_access_flags(GrVkBuffer::Type type) {
- switch (type) {
- case GrVkBuffer::kIndex_Type:
- return VK_ACCESS_INDEX_READ_BIT;
- case GrVkBuffer::kVertex_Type:
- return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
- default:
- // This helper is only called for static buffers so we should only ever see index or
- // vertex buffers types
- SkASSERT(false);
- return 0;
- }
- }
- void GrVkBuffer::internalMap(GrVkGpu* gpu, size_t size, bool* createdNewBuffer) {
- VALIDATE();
- SkASSERT(!this->vkIsMapped());
- if (!fResource->unique()) {
- if (fDesc.fDynamic) {
- // in use by the command buffer, so we need to create a new one
- fResource->recycle(gpu);
- fResource = this->createResource(gpu, fDesc);
- if (createdNewBuffer) {
- *createdNewBuffer = true;
- }
- } else {
- SkASSERT(fMapPtr);
- this->addMemoryBarrier(gpu,
- buffer_type_to_access_flags(fDesc.fType),
- VK_ACCESS_TRANSFER_WRITE_BIT,
- VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- false);
- }
- }
- if (fDesc.fDynamic) {
- const GrVkAlloc& alloc = this->alloc();
- SkASSERT(alloc.fSize > 0);
- SkASSERT(alloc.fSize >= size);
- SkASSERT(0 == fOffset);
- fMapPtr = GrVkMemory::MapAlloc(gpu, alloc);
- } else {
- if (!fMapPtr) {
- fMapPtr = new unsigned char[this->size()];
- }
- }
- VALIDATE();
- }
- void GrVkBuffer::copyCpuDataToGpuBuffer(GrVkGpu* gpu, const void* src, size_t size) {
- SkASSERT(src);
- // We should never call this method in protected contexts.
- SkASSERT(!gpu->protectedContext());
- // The vulkan api restricts the use of vkCmdUpdateBuffer to updates that are less than or equal
- // to 65536 bytes and a size the is 4 byte aligned.
- if ((size <= 65536) && (0 == (size & 0x3)) && !gpu->vkCaps().avoidUpdateBuffers()) {
- gpu->updateBuffer(this, src, this->offset(), size);
- } else {
- sk_sp<GrVkTransferBuffer> transferBuffer =
- GrVkTransferBuffer::Make(gpu, size, GrVkBuffer::kCopyRead_Type);
- if (!transferBuffer) {
- return;
- }
- char* buffer = (char*) transferBuffer->map();
- memcpy (buffer, src, size);
- transferBuffer->unmap();
- gpu->copyBuffer(transferBuffer.get(), this, 0, this->offset(), size);
- }
- this->addMemoryBarrier(gpu,
- VK_ACCESS_TRANSFER_WRITE_BIT,
- buffer_type_to_access_flags(fDesc.fType),
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
- false);
- }
- void GrVkBuffer::internalUnmap(GrVkGpu* gpu, size_t size) {
- VALIDATE();
- SkASSERT(this->vkIsMapped());
- if (fDesc.fDynamic) {
- const GrVkAlloc& alloc = this->alloc();
- SkASSERT(alloc.fSize > 0);
- SkASSERT(alloc.fSize >= size);
- // We currently don't use fOffset
- SkASSERT(0 == fOffset);
- GrVkMemory::FlushMappedAlloc(gpu, alloc, 0, size);
- GrVkMemory::UnmapAlloc(gpu, alloc);
- fMapPtr = nullptr;
- } else {
- SkASSERT(fMapPtr);
- this->copyCpuDataToGpuBuffer(gpu, fMapPtr, size);
- }
- }
- bool GrVkBuffer::vkIsMapped() const {
- VALIDATE();
- return SkToBool(fMapPtr);
- }
- bool GrVkBuffer::vkUpdateData(GrVkGpu* gpu, const void* src, size_t srcSizeInBytes,
- bool* createdNewBuffer) {
- if (srcSizeInBytes > fDesc.fSizeInBytes) {
- return false;
- }
- if (fDesc.fDynamic) {
- this->internalMap(gpu, srcSizeInBytes, createdNewBuffer);
- if (!fMapPtr) {
- return false;
- }
- memcpy(fMapPtr, src, srcSizeInBytes);
- this->internalUnmap(gpu, srcSizeInBytes);
- } else {
- this->copyCpuDataToGpuBuffer(gpu, src, srcSizeInBytes);
- }
- return true;
- }
- void GrVkBuffer::validate() const {
- SkASSERT(!fResource || kVertex_Type == fDesc.fType || kIndex_Type == fDesc.fType
- || kTexel_Type == fDesc.fType || kCopyRead_Type == fDesc.fType
- || kCopyWrite_Type == fDesc.fType || kUniform_Type == fDesc.fType);
- }
|