1
2/*
3 * Copyright 2016 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#ifndef GrVkTypes_DEFINED
10#define GrVkTypes_DEFINED
11
12#include "include/core/SkTypes.h"
13#include "include/gpu/vk/GrVkVulkan.h"
14
15#ifndef VK_VERSION_1_1
16#error Skia requires the use of Vulkan 1.1 headers
17#endif
18
19#include <functional>
20#include "include/gpu/GrTypes.h"
21
22typedef intptr_t GrVkBackendMemory;
23
24/**
25 * Types for interacting with Vulkan resources created externally to Skia. GrBackendObjects for
26 * Vulkan textures are really const GrVkImageInfo*
27 */
28struct GrVkAlloc {
29 GrVkAlloc()
30 : fMemory(VK_NULL_HANDLE)
31 , fOffset(0)
32 , fSize(0)
33 , fFlags(0)
34 , fBackendMemory(0)
35 , fUsesSystemHeap(false) {}
36
37 GrVkAlloc(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, uint32_t flags)
38 : fMemory(memory)
39 , fOffset(offset)
40 , fSize(size)
41 , fFlags(flags)
42 , fBackendMemory(0)
43 , fUsesSystemHeap(false) {}
44
45 VkDeviceMemory fMemory; // can be VK_NULL_HANDLE iff is an RT and is borrowed
46 VkDeviceSize fOffset;
47 VkDeviceSize fSize; // this can be indeterminate iff Tex uses borrow semantics
48 uint32_t fFlags;
49 GrVkBackendMemory fBackendMemory; // handle to memory allocated via GrVkMemoryAllocator.
50
51 enum Flag {
52 kNoncoherent_Flag = 0x1, // memory must be flushed to device after mapping
53 kMappable_Flag = 0x2, // memory is able to be mapped.
54 };
55
56 bool operator==(const GrVkAlloc& that) const {
57 return fMemory == that.fMemory && fOffset == that.fOffset && fSize == that.fSize &&
58 fFlags == that.fFlags && fUsesSystemHeap == that.fUsesSystemHeap;
59 }
60
61private:
62 friend class GrVkHeap; // For access to usesSystemHeap
63 bool fUsesSystemHeap;
64};
65
66// This struct is used to pass in the necessary information to create a VkSamplerYcbcrConversion
67// object for an VkExternalFormatANDROID.
68struct GrVkYcbcrConversionInfo {
69 GrVkYcbcrConversionInfo()
70 : fFormat(VK_FORMAT_UNDEFINED)
71 , fExternalFormat(0)
72 , fYcbcrModel(VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
73 , fYcbcrRange(VK_SAMPLER_YCBCR_RANGE_ITU_FULL)
74 , fXChromaOffset(VK_CHROMA_LOCATION_COSITED_EVEN)
75 , fYChromaOffset(VK_CHROMA_LOCATION_COSITED_EVEN)
76 , fChromaFilter(VK_FILTER_NEAREST)
77 , fForceExplicitReconstruction(false) {}
78
79 GrVkYcbcrConversionInfo(VkFormat format,
80 uint64_t externalFormat,
81 VkSamplerYcbcrModelConversion ycbcrModel,
82 VkSamplerYcbcrRange ycbcrRange,
83 VkChromaLocation xChromaOffset,
84 VkChromaLocation yChromaOffset,
85 VkFilter chromaFilter,
86 VkBool32 forceExplicitReconstruction,
87 VkFormatFeatureFlags formatFeatures)
88 : fFormat(format)
89 , fExternalFormat(externalFormat)
90 , fYcbcrModel(ycbcrModel)
91 , fYcbcrRange(ycbcrRange)
92 , fXChromaOffset(xChromaOffset)
93 , fYChromaOffset(yChromaOffset)
94 , fChromaFilter(chromaFilter)
95 , fForceExplicitReconstruction(forceExplicitReconstruction)
96 , fFormatFeatures(formatFeatures) {
97 SkASSERT(fYcbcrModel != VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY);
98 // Either format or externalFormat must be specified.
99 SkASSERT((fFormat != VK_FORMAT_UNDEFINED) ^ (externalFormat != 0));
100 }
101
102 GrVkYcbcrConversionInfo(VkSamplerYcbcrModelConversion ycbcrModel,
103 VkSamplerYcbcrRange ycbcrRange,
104 VkChromaLocation xChromaOffset,
105 VkChromaLocation yChromaOffset,
106 VkFilter chromaFilter,
107 VkBool32 forceExplicitReconstruction,
108 uint64_t externalFormat,
109 VkFormatFeatureFlags externalFormatFeatures)
110 : GrVkYcbcrConversionInfo(VK_FORMAT_UNDEFINED, externalFormat, ycbcrModel, ycbcrRange,
111 xChromaOffset, yChromaOffset, chromaFilter,
112 forceExplicitReconstruction, externalFormatFeatures) {}
113
114 bool operator==(const GrVkYcbcrConversionInfo& that) const {
115 // Invalid objects are not required to have all other fields initialized or matching.
116 if (!this->isValid() && !that.isValid()) {
117 return true;
118 }
119 return this->fFormat == that.fFormat &&
120 this->fExternalFormat == that.fExternalFormat &&
121 this->fYcbcrModel == that.fYcbcrModel &&
122 this->fYcbcrRange == that.fYcbcrRange &&
123 this->fXChromaOffset == that.fXChromaOffset &&
124 this->fYChromaOffset == that.fYChromaOffset &&
125 this->fChromaFilter == that.fChromaFilter &&
126 this->fForceExplicitReconstruction == that.fForceExplicitReconstruction;
127 }
128 bool operator!=(const GrVkYcbcrConversionInfo& that) const { return !(*this == that); }
129
130 bool isValid() const { return fYcbcrModel != VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; }
131
132 // Format of the source image. Must be set to VK_FORMAT_UNDEFINED for external images or
133 // a valid image format otherwise.
134 VkFormat fFormat;
135
136 // The external format. Must be non-zero for external images, zero otherwise.
137 // Should be compatible to be used in a VkExternalFormatANDROID struct.
138 uint64_t fExternalFormat;
139
140 VkSamplerYcbcrModelConversion fYcbcrModel;
141 VkSamplerYcbcrRange fYcbcrRange;
142 VkChromaLocation fXChromaOffset;
143 VkChromaLocation fYChromaOffset;
144 VkFilter fChromaFilter;
145 VkBool32 fForceExplicitReconstruction;
146
147 // For external images format features here should be those returned by a call to
148 // vkAndroidHardwareBufferFormatPropertiesANDROID
149 VkFormatFeatureFlags fFormatFeatures;
150};
151
152/*
153 * When wrapping a GrBackendTexture or GrBackendRendenderTarget, the fCurrentQueueFamily should
154 * either be VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_EXTERNAL, or VK_QUEUE_FAMILY_FOREIGN_EXT. If
155 * fSharingMode is VK_SHARING_MODE_EXCLUSIVE then fCurrentQueueFamily can also be the graphics
156 * queue index passed into Skia.
157 */
158struct GrVkImageInfo {
159 VkImage fImage;
160 GrVkAlloc fAlloc;
161 VkImageTiling fImageTiling;
162 VkImageLayout fImageLayout;
163 VkFormat fFormat;
164 uint32_t fLevelCount;
165 uint32_t fCurrentQueueFamily;
166 GrProtected fProtected;
167 GrVkYcbcrConversionInfo fYcbcrConversionInfo;
168 VkSharingMode fSharingMode;
169
170 GrVkImageInfo()
171 : fImage(VK_NULL_HANDLE)
172 , fAlloc()
173 , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
174 , fImageLayout(VK_IMAGE_LAYOUT_UNDEFINED)
175 , fFormat(VK_FORMAT_UNDEFINED)
176 , fLevelCount(0)
177 , fCurrentQueueFamily(VK_QUEUE_FAMILY_IGNORED)
178 , fProtected(GrProtected::kNo)
179 , fYcbcrConversionInfo()
180 , fSharingMode(VK_SHARING_MODE_EXCLUSIVE) {}
181
182 GrVkImageInfo(VkImage image,
183 GrVkAlloc alloc,
184 VkImageTiling imageTiling,
185 VkImageLayout layout,
186 VkFormat format,
187 uint32_t levelCount,
188 uint32_t currentQueueFamily = VK_QUEUE_FAMILY_IGNORED,
189 GrProtected isProtected = GrProtected::kNo,
190 GrVkYcbcrConversionInfo ycbcrConversionInfo = GrVkYcbcrConversionInfo(),
191 VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE)
192 : fImage(image)
193 , fAlloc(alloc)
194 , fImageTiling(imageTiling)
195 , fImageLayout(layout)
196 , fFormat(format)
197 , fLevelCount(levelCount)
198 , fCurrentQueueFamily(currentQueueFamily)
199 , fProtected(isProtected)
200 , fYcbcrConversionInfo(ycbcrConversionInfo)
201 , fSharingMode(sharingMode) {}
202
203 GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout, uint32_t familyQueueIndex)
204 : fImage(info.fImage)
205 , fAlloc(info.fAlloc)
206 , fImageTiling(info.fImageTiling)
207 , fImageLayout(layout)
208 , fFormat(info.fFormat)
209 , fLevelCount(info.fLevelCount)
210 , fCurrentQueueFamily(familyQueueIndex)
211 , fProtected(info.fProtected)
212 , fYcbcrConversionInfo(info.fYcbcrConversionInfo)
213 , fSharingMode(info.fSharingMode) {}
214
215#if GR_TEST_UTILS
216 bool operator==(const GrVkImageInfo& that) const {
217 return fImage == that.fImage && fAlloc == that.fAlloc &&
218 fImageTiling == that.fImageTiling && fImageLayout == that.fImageLayout &&
219 fFormat == that.fFormat && fLevelCount == that.fLevelCount &&
220 fCurrentQueueFamily == that.fCurrentQueueFamily && fProtected == that.fProtected &&
221 fYcbcrConversionInfo == that.fYcbcrConversionInfo &&
222 fSharingMode == that.fSharingMode;
223 }
224#endif
225};
226
227using GrVkGetProc = std::function<PFN_vkVoidFunction(
228 const char*, // function name
229 VkInstance, // instance or VK_NULL_HANDLE
230 VkDevice // device or VK_NULL_HANDLE
231 )>;
232
233/**
234 * This object is wrapped in a GrBackendDrawableInfo and passed in as an argument to
235 * drawBackendGpu() calls on an SkDrawable. The drawable will use this info to inject direct
236 * Vulkan calls into our stream of GPU draws.
237 *
238 * The SkDrawable is given a secondary VkCommandBuffer in which to record draws. The GPU backend
239 * will then execute that command buffer within a render pass it is using for its own draws. The
240 * drawable is also given the attachment of the color index, a compatible VkRenderPass, and the
241 * VkFormat of the color attachment so that it can make VkPipeline objects for the draws. The
242 * SkDrawable must not alter the state of the VkRenderpass or sub pass.
243 *
244 * Additionally, the SkDrawable may fill in the passed in fDrawBounds with the bounds of the draws
245 * that it submits to the command buffer. This will be used by the GPU backend for setting the
246 * bounds in vkCmdBeginRenderPass. If fDrawBounds is not updated, we will assume that the entire
247 * attachment may have been written to.
248 *
249 * The SkDrawable is always allowed to create its own command buffers and submit them to the queue
250 * to render offscreen textures which will be sampled in draws added to the passed in
251 * VkCommandBuffer. If this is done the SkDrawable is in charge of adding the required memory
252 * barriers to the queue for the sampled images since the Skia backend will not do this.
253 *
254 * The VkImage is informational only and should not be used or modified in any ways.
255 */
256struct GrVkDrawableInfo {
257 VkCommandBuffer fSecondaryCommandBuffer;
258 uint32_t fColorAttachmentIndex;
259 VkRenderPass fCompatibleRenderPass;
260 VkFormat fFormat;
261 VkRect2D* fDrawBounds;
262 VkImage fImage;
263};
264
265#endif
266