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 "GrVkGpu.h" 9#include "GrVkImage.h" 10#include "GrVkMemory.h" 11#include "GrVkUtil.h" 12 13#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) 14 15void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, 16 VkAccessFlags srcAccessMask, 17 VkAccessFlags dstAccessMask, 18 VkPipelineStageFlags srcStageMask, 19 VkPipelineStageFlags dstStageMask, 20 bool byRegion) { 21 SkASSERT(VK_IMAGE_LAYOUT_GENERAL != newLayout || VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout); 22 // Is this reasonable? Could someone want to keep the same layout but use the masks to force 23 // a barrier on certain things? 24 if (newLayout == fCurrentLayout) { 25 return; 26 } 27 28 VkImageMemoryBarrier imageMemoryBarrier = { 29 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 30 NULL, // pNext 31 srcAccessMask, // outputMask 32 dstAccessMask, // inputMask 33 fCurrentLayout, // oldLayout 34 newLayout, // newLayout 35 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 36 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex 37 fResource->fImage, // image 38 { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange 39 }; 40 41 // TODO: restrict to area of image we're interested in 42 gpu->addImageMemoryBarrier(srcStageMask, dstStageMask, byRegion, &imageMemoryBarrier); 43 44 fCurrentLayout = newLayout; 45} 46 47const GrVkImage::Resource* GrVkImage::CreateResource(const GrVkGpu* gpu, 48 const ImageDesc& imageDesc) { 49 VkImage image = 0; 50 VkDeviceMemory alloc; 51 52 VkResult err; 53 54 VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageDesc.fImageTiling) 55 ? VK_IMAGE_LAYOUT_PREINITIALIZED 56 : VK_IMAGE_LAYOUT_UNDEFINED; 57 58 // Create Image 59 VkSampleCountFlagBits vkSamples; 60 if (!GrSampleCountToVkSampleCount(imageDesc.fSamples, &vkSamples)) { 61 return nullptr; 62 } 63 const VkImageCreateInfo imageCreateInfo = { 64 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType 65 NULL, // pNext 66 0, // VkImageCreateFlags 67 imageDesc.fImageType, // VkImageType 68 imageDesc.fFormat, // VkFormat 69 { imageDesc.fWidth, imageDesc.fHeight, 1 }, // VkExtent3D 70 imageDesc.fLevels, // mipLevels 71 1, // arrayLayers 72 vkSamples, // samples 73 imageDesc.fImageTiling, // VkImageTiling 74 imageDesc.fUsageFlags, // VkImageUsageFlags 75 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode 76 0, // queueFamilyCount 77 0, // pQueueFamilyIndices 78 initialLayout // initialLayout 79 }; 80 81 err = VK_CALL(gpu, CreateImage(gpu->device(), &imageCreateInfo, nullptr, &image)); 82 SkASSERT(!err); 83 84 if (!GrVkMemory::AllocAndBindImageMemory(gpu, image, imageDesc.fMemProps, &alloc)) { 85 VK_CALL(gpu, DestroyImage(gpu->device(), image, nullptr)); 86 return nullptr; 87 } 88 89 GrVkImage::Resource::Flags flags = 90 (VK_IMAGE_TILING_LINEAR == imageDesc.fImageTiling) ? Resource::kLinearTiling_Flag 91 : Resource::kNo_Flags; 92 93 return (new GrVkImage::Resource(image, alloc, flags)); 94} 95 96GrVkImage::~GrVkImage() { 97 // should have been released or abandoned first 98 SkASSERT(!fResource); 99} 100 101void GrVkImage::releaseImage(const GrVkGpu* gpu) { 102 if (fResource) { 103 fResource->unref(gpu); 104 fResource = nullptr; 105 } 106} 107 108void GrVkImage::abandonImage() { 109 if (fResource) { 110 fResource->unrefAndAbandon(); 111 fResource = nullptr; 112 } 113} 114 115void GrVkImage::Resource::freeGPUData(const GrVkGpu* gpu) const { 116 VK_CALL(gpu, DestroyImage(gpu->device(), fImage, nullptr)); 117 VK_CALL(gpu, FreeMemory(gpu->device(), fAlloc, nullptr)); 118}