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 #ifndef GrVkImage_DEFINED 9 #define GrVkImage_DEFINED 10 11 #include "include/core/SkTypes.h" 12 #include "include/gpu/GrBackendSurface.h" 13 #include "include/gpu/vk/GrVkTypes.h" 14 #include "include/private/GrTypesPriv.h" 15 #include "include/private/GrVkTypesPriv.h" 16 #include "src/gpu/GrAttachment.h" 17 #include "src/gpu/GrBackendSurfaceMutableStateImpl.h" 18 #include "src/gpu/GrManagedResource.h" 19 #include "src/gpu/GrRefCnt.h" 20 #include "src/gpu/GrTexture.h" 21 #include "src/gpu/vk/GrVkDescriptorSet.h" 22 23 #include <cinttypes> 24 25 class GrVkGpu; 26 class GrVkImageView; 27 28 class SK_API GrVkImage : public GrAttachment { 29 private: 30 class Resource; 31 32 public: 33 static sk_sp<GrVkImage> MakeStencil(GrVkGpu* gpu, 34 SkISize dimensions, 35 int sampleCnt, 36 VkFormat format); 37 38 static sk_sp<GrVkImage> MakeMSAA(GrVkGpu* gpu, 39 SkISize dimensions, 40 int numSamples, 41 VkFormat format, 42 GrProtected isProtected, 43 GrMemoryless memoryless); 44 45 static sk_sp<GrVkImage> MakeTexture(GrVkGpu* gpu, 46 SkISize dimensions, 47 VkFormat format, 48 uint32_t mipLevels, 49 GrRenderable renderable, 50 int numSamples, 51 SkBudgeted budgeted, 52 GrProtected isProtected); 53 54 static sk_sp<GrVkImage> MakeWrapped(GrVkGpu* gpu, 55 SkISize dimensions, 56 const GrVkImageInfo&, 57 sk_sp<GrBackendSurfaceMutableStateImpl>, 58 UsageFlags attachmentUsages, 59 GrWrapOwnership, 60 GrWrapCacheable, 61 bool forSecondaryCB = false); 62 63 ~GrVkImage() override; 64 image()65 VkImage image() const { 66 // Should only be called when we have a real fResource object, i.e. never when being used as 67 // a RT in an external secondary command buffer. 68 SkASSERT(fResource); 69 return fInfo.fImage; 70 } alloc()71 const GrVkAlloc& alloc() const { 72 // Should only be called when we have a real fResource object, i.e. never when being used as 73 // a RT in an external secondary command buffer. 74 SkASSERT(fResource); 75 return fInfo.fAlloc; 76 } vkImageInfo()77 const GrVkImageInfo& vkImageInfo() const { return fInfo; } imageFormat()78 VkFormat imageFormat() const { return fInfo.fFormat; } backendFormat()79 GrBackendFormat backendFormat() const override { 80 bool usesDRMModifier = 81 this->vkImageInfo().fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; 82 if (fResource && this->ycbcrConversionInfo().isValid()) { 83 SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat); 84 return GrBackendFormat::MakeVk(this->ycbcrConversionInfo(), usesDRMModifier); 85 } 86 SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED); 87 return GrBackendFormat::MakeVk(this->imageFormat(), usesDRMModifier); 88 } mipLevels()89 uint32_t mipLevels() const { return fInfo.fLevelCount; } ycbcrConversionInfo()90 const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const { 91 // Should only be called when we have a real fResource object, i.e. never when being used as 92 // a RT in an external secondary command buffer. 93 SkASSERT(fResource); 94 return fInfo.fYcbcrConversionInfo; 95 } vkUsageFlags()96 VkImageUsageFlags vkUsageFlags() { return fInfo.fImageUsageFlags; } supportsInputAttachmentUsage()97 bool supportsInputAttachmentUsage() const { 98 return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 99 } 100 framebufferView()101 const GrVkImageView* framebufferView() const { return fFramebufferView.get(); } textureView()102 const GrVkImageView* textureView() const { return fTextureView.get(); } 103 104 // So that we don't need to rewrite descriptor sets each time, we keep cached input descriptor 105 // sets on the attachment and simply reuse those descriptor sets for this attachment only. These 106 // calls will fail if the attachment does not support being used as an input attachment. These 107 // calls do not ref the GrVkDescriptorSet so they called will need to manually ref them if they 108 // need to be kept alive. 109 gr_rp<const GrVkDescriptorSet> inputDescSetForBlending(GrVkGpu* gpu); 110 // Input descripotr set used when needing to read a resolve attachment to load data into a 111 // discardable msaa attachment. 112 gr_rp<const GrVkDescriptorSet> inputDescSetForMSAALoad(GrVkGpu* gpu); 113 resource()114 const Resource* resource() const { 115 SkASSERT(fResource); 116 return fResource; 117 } isLinearTiled()118 bool isLinearTiled() const { 119 // Should only be called when we have a real fResource object, i.e. never when being used as 120 // a RT in an external secondary command buffer. 121 SkASSERT(fResource); 122 return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling); 123 } isBorrowed()124 bool isBorrowed() const { return fIsBorrowed; } 125 getMutableState()126 sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; } 127 currentLayout()128 VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); } 129 130 void setImageLayoutAndQueueIndex(const GrVkGpu* gpu, 131 VkImageLayout newLayout, 132 VkAccessFlags dstAccessMask, 133 VkPipelineStageFlags dstStageMask, 134 bool byRegion, 135 uint32_t newQueueFamilyIndex); 136 setImageLayout(const GrVkGpu * gpu,VkImageLayout newLayout,VkAccessFlags dstAccessMask,VkPipelineStageFlags dstStageMask,bool byRegion)137 void setImageLayout(const GrVkGpu* gpu, 138 VkImageLayout newLayout, 139 VkAccessFlags dstAccessMask, 140 VkPipelineStageFlags dstStageMask, 141 bool byRegion) { 142 this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion, 143 VK_QUEUE_FAMILY_IGNORED); 144 } 145 currentQueueFamilyIndex()146 uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); } 147 setQueueFamilyIndex(uint32_t queueFamilyIndex)148 void setQueueFamilyIndex(uint32_t queueFamilyIndex) { 149 fMutableState->setQueueFamilyIndex(queueFamilyIndex); 150 } 151 152 // Returns the image to its original queue family and changes the layout to present if the queue 153 // family is not external or foreign. 154 void prepareForPresent(GrVkGpu* gpu); 155 156 // Returns the image to its original queue family 157 void prepareForExternal(GrVkGpu* gpu); 158 159 // This simply updates our tracking of the image layout and does not actually do any gpu work. 160 // This is only used for mip map generation where we are manually changing the layouts as we 161 // blit each layer, and then at the end need to update our tracking. updateImageLayout(VkImageLayout newLayout)162 void updateImageLayout(VkImageLayout newLayout) { 163 // Should only be called when we have a real fResource object, i.e. never when being used as 164 // a RT in an external secondary command buffer. 165 SkASSERT(fResource); 166 fMutableState->setImageLayout(newLayout); 167 } 168 169 struct ImageDesc { 170 VkImageType fImageType; 171 VkFormat fFormat; 172 uint32_t fWidth; 173 uint32_t fHeight; 174 uint32_t fLevels; 175 uint32_t fSamples; 176 VkImageTiling fImageTiling; 177 VkImageUsageFlags fUsageFlags; 178 VkFlags fMemProps; 179 GrProtected fIsProtected; 180 ImageDescImageDesc181 ImageDesc() 182 : fImageType(VK_IMAGE_TYPE_2D) 183 , fFormat(VK_FORMAT_UNDEFINED) 184 , fWidth(0) 185 , fHeight(0) 186 , fLevels(1) 187 , fSamples(1) 188 , fImageTiling(VK_IMAGE_TILING_OPTIMAL) 189 , fUsageFlags(0) 190 , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) 191 , fIsProtected(GrProtected::kNo) {} 192 }; 193 194 static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*); 195 // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo 196 static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*); 197 198 // These match the definitions in SkImage, for whence they came 199 typedef void* ReleaseCtx; 200 typedef void (*ReleaseProc)(ReleaseCtx); 201 202 void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper); 203 204 // Helpers to use for setting the layout of the VkImage 205 static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout); 206 static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); 207 208 size_t onGpuMemorySize() const override; 209 #if GR_TEST_UTILS 210 void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu); 211 #endif 212 213 private: 214 static sk_sp<GrVkImage> Make(GrVkGpu* gpu, 215 SkISize dimensions, 216 UsageFlags attachmentUsages, 217 int sampleCnt, 218 VkFormat format, 219 uint32_t mipLevels, 220 VkImageUsageFlags vkUsageFlags, 221 GrProtected isProtected, 222 GrMemoryless, 223 SkBudgeted); 224 225 GrVkImage(GrVkGpu* gpu, 226 SkISize dimensions, 227 UsageFlags supportedUsages, 228 const GrVkImageInfo&, 229 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, 230 sk_sp<const GrVkImageView> framebufferView, 231 sk_sp<const GrVkImageView> textureView, 232 SkBudgeted); 233 234 GrVkImage(GrVkGpu* gpu, 235 SkISize dimensions, 236 UsageFlags supportedUsages, 237 const GrVkImageInfo&, 238 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, 239 sk_sp<const GrVkImageView> framebufferView, 240 sk_sp<const GrVkImageView> textureView, 241 GrBackendObjectOwnership, 242 GrWrapCacheable, 243 bool forSecondaryCB); 244 245 void init(GrVkGpu*, bool forSecondaryCB); 246 247 void onRelease() override; 248 void onAbandon() override; 249 250 void releaseImage(); hasResource()251 bool hasResource() const { return fResource; } 252 253 GrVkGpu* getVkGpu() const; 254 255 GrVkImageInfo fInfo; 256 uint32_t fInitialQueueFamily; 257 sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState; 258 259 sk_sp<const GrVkImageView> fFramebufferView; 260 sk_sp<const GrVkImageView> fTextureView; 261 262 bool fIsBorrowed; 263 264 // Descriptor set used when this is used as an input attachment for reading the dst in blending. 265 gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet; 266 // Descriptor set used when this is used as an input attachment for loading an msaa attachment. 267 gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet; 268 269 class Resource : public GrTextureResource { 270 public: Resource(const GrVkGpu * gpu)271 explicit Resource(const GrVkGpu* gpu) 272 : fGpu(gpu) 273 , fImage(VK_NULL_HANDLE) { 274 fAlloc.fMemory = VK_NULL_HANDLE; 275 fAlloc.fOffset = 0; 276 } 277 Resource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)278 Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling) 279 : fGpu(gpu) 280 , fImage(image) 281 , fAlloc(alloc) {} 282 ~Resource()283 ~Resource() override {} 284 285 #ifdef SK_TRACE_MANAGED_RESOURCES dumpInfo()286 void dumpInfo() const override { 287 SkDebugf("GrVkImage: %" PRIdPTR " (%d refs)\n", (intptr_t)fImage, this->getRefCnt()); 288 } 289 #endif 290 291 #ifdef SK_DEBUG asVkImageResource()292 const GrManagedResource* asVkImageResource() const override { return this; } 293 #endif 294 295 private: 296 void freeGPUData() const override; 297 298 const GrVkGpu* fGpu; 299 VkImage fImage; 300 GrVkAlloc fAlloc; 301 302 using INHERITED = GrTextureResource; 303 }; 304 305 // for wrapped textures 306 class BorrowedResource : public Resource { 307 public: BorrowedResource(const GrVkGpu * gpu,VkImage image,const GrVkAlloc & alloc,VkImageTiling tiling)308 BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, 309 VkImageTiling tiling) 310 : Resource(gpu, image, alloc, tiling) { 311 } 312 private: 313 void freeGPUData() const override; 314 }; 315 316 Resource* fResource; 317 318 friend class GrVkRenderTarget; 319 }; 320 321 #endif 322