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 "GrVkTextureRenderTarget.h"
9 
10 #include "GrRenderTargetPriv.h"
11 #include "GrVkGpu.h"
12 #include "GrVkImageView.h"
13 #include "GrVkUtil.h"
14 
15 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
16 
17 GrVkTextureRenderTarget*
Create(GrVkGpu * gpu,const GrSurfaceDesc & desc,GrGpuResource::LifeCycle lifeCycle,VkFormat format,const GrVkImage::Resource * imageResource)18 GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
19                                 const GrSurfaceDesc& desc,
20                                 GrGpuResource::LifeCycle lifeCycle,
21                                 VkFormat format,
22                                 const GrVkImage::Resource* imageResource) {
23 
24     VkImage image = imageResource->fImage;
25     // Create the texture ImageView
26     const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, format,
27                                                            GrVkImageView::kColor_Type);
28     if (!imageView) {
29         return nullptr;
30     }
31 
32     VkFormat pixelFormat;
33     GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
34 
35     VkImage colorImage;
36 
37     // create msaa surface if necessary
38     const GrVkImage::Resource* msaaImageResource = nullptr;
39     const GrVkImageView* resolveAttachmentView = nullptr;
40     if (desc.fSampleCnt) {
41         GrVkImage::ImageDesc msImageDesc;
42         msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
43         msImageDesc.fFormat = pixelFormat;
44         msImageDesc.fWidth = desc.fWidth;
45         msImageDesc.fHeight = desc.fHeight;
46         msImageDesc.fLevels = 1;
47         msImageDesc.fSamples = desc.fSampleCnt;
48         msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
49         msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
50         msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
51 
52         msaaImageResource = GrVkImage::CreateResource(gpu, msImageDesc);
53 
54         if (!msaaImageResource) {
55             imageView->unref(gpu);
56             return nullptr;
57         }
58 
59         // Set color attachment image
60         colorImage = msaaImageResource->fImage;
61 
62         // Create resolve attachment view if necessary.
63         // If the format matches, this is the same as the texture imageView.
64         if (pixelFormat == format) {
65             resolveAttachmentView = imageView;
66             resolveAttachmentView->ref();
67         } else {
68             resolveAttachmentView = GrVkImageView::Create(gpu, image, pixelFormat,
69                                                           GrVkImageView::kColor_Type);
70             if (!resolveAttachmentView) {
71                 msaaImageResource->unref(gpu);
72                 imageView->unref(gpu);
73                 return nullptr;
74             }
75         }
76     } else {
77         // Set color attachment image
78         colorImage = imageResource->fImage;
79     }
80 
81     const GrVkImageView* colorAttachmentView;
82     // Get color attachment view.
83     // If the format matches and there's no multisampling,
84     // this is the same as the texture imageView
85     if (pixelFormat == format && !resolveAttachmentView) {
86         colorAttachmentView = imageView;
87         colorAttachmentView->ref();
88     } else {
89         colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
90                                                     GrVkImageView::kColor_Type);
91         if (!colorAttachmentView) {
92             if (msaaImageResource) {
93                 resolveAttachmentView->unref(gpu);
94                 msaaImageResource->unref(gpu);
95             }
96             imageView->unref(gpu);
97             return nullptr;
98         }
99     }
100 
101     GrVkTextureRenderTarget* texRT;
102     if (msaaImageResource) {
103         texRT = new GrVkTextureRenderTarget(gpu, desc, lifeCycle,
104                                             imageResource, imageView, msaaImageResource,
105                                             colorAttachmentView,
106                                             resolveAttachmentView);
107         msaaImageResource->unref(gpu);
108     } else {
109         texRT = new GrVkTextureRenderTarget(gpu, desc, lifeCycle,
110                                             imageResource, imageView,
111                                             colorAttachmentView);
112     }
113     return texRT;
114 }
115 
116 GrVkTextureRenderTarget*
CreateNewTextureRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,GrGpuResource::LifeCycle lifeCycle,const GrVkImage::ImageDesc & imageDesc)117 GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
118                                                      const GrSurfaceDesc& desc,
119                                                      GrGpuResource::LifeCycle lifeCycle,
120                                                      const GrVkImage::ImageDesc& imageDesc) {
121     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
122     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
123 
124     const GrVkImage::Resource* imageRsrc = GrVkImage::CreateResource(gpu, imageDesc);
125 
126     if (!imageRsrc) {
127         return nullptr;
128     }
129 
130     GrVkTextureRenderTarget* trt = GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle,
131                                                                    imageDesc.fFormat, imageRsrc);
132     // Create() will increment the refCount of the image resource if it succeeds
133     imageRsrc->unref(gpu);
134 
135     return trt;
136 }
137 
138 GrVkTextureRenderTarget*
CreateWrappedTextureRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,GrGpuResource::LifeCycle lifeCycle,VkFormat format,GrVkImage::Resource * imageRsrc)139 GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(GrVkGpu* gpu,
140                                                           const GrSurfaceDesc& desc,
141                                                           GrGpuResource::LifeCycle lifeCycle,
142                                                           VkFormat format,
143                                                           GrVkImage::Resource* imageRsrc) {
144     SkASSERT(imageRsrc);
145 
146     // Note: we assume the caller will unref the imageResource
147     // Create() will increment the refCount, and we'll unref when we're done with it
148     return GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle, format, imageRsrc);
149 }
150 
151