Flutter Engine
The Flutter Engine
GrVkRenderTarget.cpp
Go to the documentation of this file.
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
9
27
28#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
29
30static int renderpass_features_to_index(bool hasResolve, bool hasStencil,
32 GrVkRenderPass::LoadFromResolve loadFromReslove) {
33 int index = 0;
34 if (hasResolve) {
35 index += 1;
36 }
37 if (hasStencil) {
38 index += 2;
39 }
41 index += 4;
42 }
44 index += 8;
45 }
46 if (loadFromReslove == GrVkRenderPass::LoadFromResolve::kLoad) {
47 index += 16;
48 }
49 return index;
50}
51
52// We're virtually derived from GrSurface (via GrRenderTarget) so its
53// constructor must be explicitly called.
55 SkISize dimensions,
56 sk_sp<GrVkImage> colorAttachment,
57 sk_sp<GrVkImage> resolveAttachment,
58 CreateType createType,
59 std::string_view label)
60 : GrSurface(gpu,
61 dimensions,
62 colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo,
63 label)
64 // for the moment we only support 1:1 color to stencil
65 , GrRenderTarget(gpu,
66 dimensions,
67 colorAttachment->numSamples(),
68 colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo,
69 label)
70 , fColorAttachment(std::move(colorAttachment))
71 , fResolveAttachment(std::move(resolveAttachment))
72 , fCachedFramebuffers() {
73 SkASSERT(fColorAttachment);
74
75 if (fColorAttachment->numSamples() == 1 && fColorAttachment->supportsInputAttachmentUsage()) {
76 SkASSERT(!fResolveAttachment);
77 // When we have a single sampled color attachment, we set both the color and resolve
78 // to the same attachment. This way if we use DMAA on this render target we will resolve
79 // to the single target attachment.
80 fResolveAttachment = fColorAttachment;
81 }
82
83 SkASSERT(!fResolveAttachment ||
84 (fResolveAttachment->isProtected() == fColorAttachment->isProtected()));
86 this->setFlags();
87 if (createType == CreateType::kDirectlyWrapped) {
89 }
90}
91
93 SkISize dimensions,
94 sk_sp<GrVkFramebuffer> externalFramebuffer,
95 std::string_view label)
96 : GrSurface(gpu,
97 dimensions,
98 externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
100 label)
101 , GrRenderTarget(gpu,
102 dimensions,
103 1,
104 externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
105 : GrProtected::kNo,
106 label)
107 , fCachedFramebuffers()
108 , fExternalFramebuffer(externalFramebuffer) {
109 SkASSERT(fExternalFramebuffer);
110 SkASSERT(!fColorAttachment);
111 SkDEBUGCODE(auto colorAttachment = fExternalFramebuffer->colorAttachment());
116 this->setFlags();
118}
119
120void GrVkRenderTarget::setFlags() {
121 if (this->wrapsSecondaryCommandBuffer()) {
122 return;
123 }
125 if (nonMSAAAttachment && nonMSAAAttachment->supportsInputAttachmentUsage()) {
127 }
128}
129
131 GrVkGpu* gpu,
132 SkISize dimensions,
133 int sampleCnt,
134 const GrVkImageInfo& info,
136 SkASSERT(VK_NULL_HANDLE != info.fImage);
137 SkASSERT(1 == info.fLevelCount);
138 SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
139
140 int wrappedImageSampleCnt = static_cast<int>(info.fSampleCount);
141 if (sampleCnt != wrappedImageSampleCnt && wrappedImageSampleCnt != 1) {
142 return nullptr;
143 }
144
145 sk_sp<GrVkImage> wrappedAttachment =
148 info,
149 std::move(mutableState),
153 /*label=*/"VkImage_WrappedAttachment");
154 if (!wrappedAttachment) {
155 return nullptr;
156 }
157
159 colorAttachment = std::move(wrappedAttachment);
160
161 if (!colorAttachment) {
162 return nullptr;
163 }
164
165 GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu,
167 std::move(colorAttachment),
168 nullptr,
170 /*label=*/"Vk_MakeWrappedRenderTarget");
171 return sk_sp<GrVkRenderTarget>(vkRT);
172}
173
175 GrVkGpu* gpu, SkISize dimensions, const GrVkDrawableInfo& vkInfo) {
178 if (!rp) {
179 return nullptr;
180 }
181
183 return nullptr;
184 }
185
186 // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
187 // others we keep at the default "null" values.
190 info.fFormat = vkInfo.fFormat;
193
194 auto mutableState =
195 sk_make_sp<skgpu::MutableTextureState>(skgpu::MutableTextureStates::MakeVulkan(
197
201 info,
202 std::move(mutableState),
206 "VkImage_ColorAttachment",
207 true);
208
209 std::unique_ptr<GrVkSecondaryCommandBuffer> scb(
211 if (!scb) {
212 return nullptr;
213 }
214
216 gpu, std::move(colorAttachment), sk_sp<const GrVkRenderPass>(rp),
217 std::move(scb)));
218
219 GrVkRenderTarget* vkRT =
220 new GrVkRenderTarget(gpu, dimensions, std::move(framebuffer),
221 /*label=*/"Vk_MakeSecondaryCBRenderTarget");
222
223 return sk_sp<GrVkRenderTarget>(vkRT);
224}
225
227 if (this->wrapsSecondaryCommandBuffer()) {
228 return fExternalFramebuffer->colorAttachment()->backendFormat();
229 }
230 return fColorAttachment->backendFormat();
231}
232
234 if (fColorAttachment->numSamples() == 1) {
235 return fColorAttachment.get();
236 } else {
237 return fResolveAttachment.get();
238 }
239}
240
241GrVkImage* GrVkRenderTarget::dynamicMSAAAttachment() {
242 if (fDynamicMSAAAttachment) {
243 return fDynamicMSAAAttachment.get();
244 }
245 const GrVkImage* nonMSAAColorAttachment = this->colorAttachment();
246 SkASSERT(nonMSAAColorAttachment->numSamples() == 1);
247
248 GrVkGpu* gpu = this->getVkGpu();
249 auto rp = gpu->getContext()->priv().resourceProvider();
250
251 const GrBackendFormat& format = nonMSAAColorAttachment->backendFormat();
252
253 GrMemoryless memoryless =
255
256 sk_sp<GrAttachment> msaaAttachment =
257 rp->getDiscardableMSAAAttachment(nonMSAAColorAttachment->dimensions(),
258 format,
260 GrProtected(nonMSAAColorAttachment->isProtected()),
261 memoryless);
262 if (!msaaAttachment) {
263 return nullptr;
264 }
265 fDynamicMSAAAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
266 return fDynamicMSAAAttachment.get();
267}
268
269GrVkImage* GrVkRenderTarget::msaaAttachment() {
270 return this->colorAttachment()->numSamples() == 1 ? this->dynamicMSAAAttachment()
271 : this->colorAttachment();
272}
273
274bool GrVkRenderTarget::canAttemptStencilAttachment(bool useMSAASurface) const {
275 SkASSERT(!useMSAASurface || this->numSamples() > 1 ||
276 this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA());
277 if (!useMSAASurface && this->numSamples() > 1) {
278 return false;
279 }
280 bool validMSAA = true;
281 if (useMSAASurface) {
282 validMSAA = this->numSamples() > 1 ||
283 (this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA() &&
285 }
286 // We don't know the status of the stencil attachment for wrapped external secondary command
287 // buffers so we just assume we don't have one.
288 return validMSAA && !this->wrapsSecondaryCommandBuffer();
289}
290
291bool GrVkRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
293 SkASSERT(!useMSAASurface ||
294 this->numSamples() > 1 ||
295 this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA());
296 return true;
297}
298
300 return fExternalFramebuffer;
301}
302
303GrVkResourceProvider::CompatibleRPHandle GrVkRenderTarget::compatibleRenderPassHandle(
304 bool withResolve,
305 bool withStencil,
306 SelfDependencyFlags selfDepFlags,
307 LoadFromResolve loadFromResolve) {
309
310 const GrVkFramebuffer* fb =
311 this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
312 if (!fb) {
313 return {};
314 }
315
316 return fb->compatibleRenderPassHandle();
317}
318
320 bool withStencil,
321 SelfDependencyFlags selfDepFlags,
322 LoadFromResolve loadFromResolve) {
323 if (this->wrapsSecondaryCommandBuffer()) {
324 return fExternalFramebuffer->externalRenderPass();
325 }
326
327 const GrVkFramebuffer* fb =
328 this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
329 if (!fb) {
330 return nullptr;
331 }
332
333 return fb->compatibleRenderPass();
334}
335
336std::pair<const GrVkRenderPass*, GrVkResourceProvider::CompatibleRPHandle>
337GrVkRenderTarget::createSimpleRenderPass(bool withResolve,
338 bool withStencil,
339 SelfDependencyFlags selfDepFlags,
340 LoadFromResolve loadFromResolve) {
342
343 GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();
344
345 GrVkResourceProvider::CompatibleRPHandle handle;
346 const GrVkRenderPass* renderPass = rp.findCompatibleRenderPass(
347 this, &handle, withResolve, withStencil, selfDepFlags,
348 loadFromResolve);
349 SkASSERT(!renderPass || handle.isValid());
350 return {renderPass, handle};
351}
352
354 bool withStencil,
355 SelfDependencyFlags selfDepFlags,
356 LoadFromResolve loadFromResolve) {
357 int cacheIndex =
358 renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
359 SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
360 if (auto fb = fCachedFramebuffers[cacheIndex]) {
361 return fb.get();
362 }
363
364 this->createFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
365 return fCachedFramebuffers[cacheIndex].get();
366}
367
368void GrVkRenderTarget::createFramebuffer(bool withResolve,
369 bool withStencil,
370 SelfDependencyFlags selfDepFlags,
371 LoadFromResolve loadFromResolve) {
373 GrVkGpu* gpu = this->getVkGpu();
374
375 auto[renderPass, compatibleHandle] =
376 this->createSimpleRenderPass(withResolve, withStencil, selfDepFlags, loadFromResolve);
377 if (!renderPass) {
378 return;
379 }
380 SkASSERT(compatibleHandle.isValid());
381
382 int cacheIndex =
383 renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
384 SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
385
386 GrVkImage* resolve = withResolve ? this->resolveAttachment() : nullptr;
387 GrVkImage* colorAttachment = withResolve ? this->msaaAttachment() : this->colorAttachment();
388
389 // Stencil attachment view is stored in the base RT stencil attachment
390 bool useMSAA = this->numSamples() > 1 || withResolve;
391 GrVkImage* stencil = withStencil ? static_cast<GrVkImage*>(this->getStencilAttachment(useMSAA))
392 : nullptr;
393 fCachedFramebuffers[cacheIndex] =
395 sk_sp<const GrVkRenderPass>(renderPass),
396 colorAttachment, resolve, stencil, compatibleHandle);
397}
398
400 GrVkRenderPass::AttachmentFlags* attachmentFlags,
401 bool withResolve,
402 bool withStencil) {
405 withResolve ? this->msaaAttachment() : this->colorAttachment();
406 if (!colorAttachment) {
407 SkDebugf("WARNING: Invalid color attachment -- possibly dmsaa attachment creation failed?");
408 return false;
409 }
410
411 desc->fColor.fFormat = colorAttachment->imageFormat();
412 desc->fColor.fSamples = colorAttachment->numSamples();
413 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
414 uint32_t attachmentCount = 1;
415
416 if (withResolve) {
417 desc->fResolve.fFormat = desc->fColor.fFormat;
418 desc->fResolve.fSamples = 1;
419 *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
420 ++attachmentCount;
421 }
422
423 if (withStencil) {
424 bool useMSAA = this->numSamples() > 1 || withResolve;
425 const GrAttachment* stencil = this->getStencilAttachment(useMSAA);
426 SkASSERT(stencil);
427 const GrVkImage* vkStencil = static_cast<const GrVkImage*>(stencil);
428 desc->fStencil.fFormat = vkStencil->imageFormat();
429 desc->fStencil.fSamples = vkStencil->numSamples();
430 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
431 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
432 ++attachmentCount;
433 }
434 desc->fAttachmentCount = attachmentCount;
435
436 return true;
437}
438
440 const GrProgramInfo& programInfo,
445
446 desc->fColor.fFormat = format;
447 desc->fColor.fSamples = programInfo.numSamples();
449 uint32_t attachmentCount = 1;
450
451 if (vkCaps.programInfoWillUseDiscardableMSAA(programInfo)) {
452 desc->fResolve.fFormat = desc->fColor.fFormat;
453 desc->fResolve.fSamples = 1;
455 ++attachmentCount;
456 }
457
458 SkASSERT(!programInfo.isStencilEnabled() || programInfo.needsStencil());
459 if (programInfo.needsStencil()) {
460 VkFormat stencilFormat = vkCaps.preferredStencilFormat();
461 desc->fStencil.fFormat = stencilFormat;
462 desc->fStencil.fSamples = programInfo.numSamples();
463 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
465 ++attachmentCount;
466 }
467 desc->fAttachmentCount = attachmentCount;
468}
469
471 // either release or abandon should have been called by the owner of this object.
472 SkASSERT(!fColorAttachment);
473 SkASSERT(!fResolveAttachment);
474 SkASSERT(!fDynamicMSAAAttachment);
475
476 for (int i = 0; i < kNumCachedFramebuffers; ++i) {
477 SkASSERT(!fCachedFramebuffers[i]);
478 }
479
480 SkASSERT(!fCachedInputDescriptorSet);
481}
482
483void GrVkRenderTarget::releaseInternalObjects() {
484 fColorAttachment.reset();
485 fResolveAttachment.reset();
486 fDynamicMSAAAttachment.reset();
487
488 for (int i = 0; i < kNumCachedFramebuffers; ++i) {
489 if (fCachedFramebuffers[i]) {
490 fCachedFramebuffers[i].reset();
491 }
492 }
493
494 if (fCachedInputDescriptorSet) {
495 fCachedInputDescriptorSet->recycle();
496 fCachedInputDescriptorSet = nullptr;
497 }
498
499 fExternalFramebuffer.reset();
500}
501
503 this->releaseInternalObjects();
505}
506
508 this->releaseInternalObjects();
510}
511
514 // This should only get called with a non-released GrVkRenderTargets.
515 SkASSERT(!this->wasDestroyed());
516 // If we have a resolve attachment that is what we return for the backend render target
517 const GrVkImage* beAttachment = this->externalAttachment();
518 return GrBackendRenderTargets::MakeVk(beAttachment->width(),
519 beAttachment->height(),
520 beAttachment->vkImageInfo(),
521 beAttachment->getMutableState());
522}
523
524GrVkGpu* GrVkRenderTarget::getVkGpu() const {
525 SkASSERT(!this->wasDestroyed());
526 return static_cast<GrVkGpu*>(this->getGpu());
527}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
@ kBorrow_GrWrapOwnership
Definition: GrTypesPriv.h:79
GrMemoryless
Definition: GrTypesPriv.h:123
static int renderpass_features_to_index(bool hasResolve, bool hasStencil, GrVkRenderPass::SelfDependencyFlags selfDepFlags, GrVkRenderPass::LoadFromResolve loadFromReslove)
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
int numSamples() const
Definition: GrAttachment.h:38
int internalMultisampleCount(const GrBackendFormat &format) const
Definition: GrCaps.h:271
GrResourceProvider * resourceProvider()
GrDirectContextPriv priv()
GrGpu * getGpu() const
bool wasDestroyed() const
void registerWithCacheWrapped(GrWrapCacheable)
const GrCaps * caps() const
Definition: GrGpu.h:73
GrDirectContext * getContext()
Definition: GrGpu.h:67
int numSamples() const
Definition: GrProgramInfo.h:29
bool isStencilEnabled() const
Definition: GrProgramInfo.h:31
int needsStencil() const
Definition: GrProgramInfo.h:30
const GrBackendFormat & backendFormat() const
Definition: GrProgramInfo.h:37
GrAttachment * getStencilAttachment() const
void onAbandon() override
void onRelease() override
int numSamples() const
SkISize dimensions() const
Definition: GrSurface.h:27
bool isProtected() const
Definition: GrSurface.h:87
int height() const
Definition: GrSurface.h:37
void setVkRTSupportsInputAttachment()
Definition: GrSurface.h:135
int width() const
Definition: GrSurface.h:32
GrInternalSurfaceFlags flags() const
Definition: GrSurface.h:68
bool programInfoWillUseDiscardableMSAA(const GrProgramInfo &) const
Definition: GrVkCaps.cpp:1796
bool supportsDiscardableMSAAForDMSAA() const
Definition: GrVkCaps.h:262
bool supportsMemorylessAttachments() const
Definition: GrVkCaps.h:268
VkFormat preferredStencilFormat() const
Definition: GrVkCaps.h:104
const GrVkRenderPass * compatibleRenderPass() const
GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle() const
const GrVkRenderPass * externalRenderPass() const
GrVkImage * colorAttachment()
static sk_sp< const GrVkFramebuffer > Make(GrVkGpu *gpu, SkISize dimensions, sk_sp< const GrVkRenderPass > compatibleRenderPass, GrVkImage *colorAttachment, GrVkImage *resolveAttachment, GrVkImage *stencilAttachment, GrVkResourceProvider::CompatibleRPHandle)
const GrVkCaps & vkCaps() const
Definition: GrVkGpu.h:61
GrVkResourceProvider & resourceProvider()
Definition: GrVkGpu.h:83
GrBackendFormat backendFormat() const override
Definition: GrVkImage.h:84
bool supportsInputAttachmentUsage() const
Definition: GrVkImage.h:102
VkFormat imageFormat() const
Definition: GrVkImage.h:83
sk_sp< skgpu::MutableTextureState > getMutableState() const
Definition: GrVkImage.h:131
VkImageUsageFlags vkUsageFlags()
Definition: GrVkImage.h:101
static sk_sp< GrVkImage > MakeWrapped(GrVkGpu *gpu, SkISize dimensions, const GrVkImageInfo &, sk_sp< skgpu::MutableTextureState >, UsageFlags attachmentUsages, GrWrapOwnership, GrWrapCacheable, std::string_view label, bool forSecondaryCB=false)
Definition: GrVkImage.cpp:179
const GrVkImageInfo & vkImageInfo() const
Definition: GrVkImage.h:82
GrBackendRenderTarget getBackendRenderTarget() const override
bool getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor *desc, GrVkRenderPass::AttachmentFlags *flags, bool withResolve, bool withStencil)
~GrVkRenderTarget() override
bool wrapsSecondaryCommandBuffer() const
GrVkImage * externalAttachment() const
sk_sp< GrVkFramebuffer > externalFramebuffer() const
GrVkImage * nonMSAAAttachment() const
bool canAttemptStencilAttachment(bool useMSAASurface) const override
void onAbandon() override
static void ReconstructAttachmentsDescriptor(const GrVkCaps &vkCaps, const GrProgramInfo &programInfo, GrVkRenderPass::AttachmentsDescriptor *desc, GrVkRenderPass::AttachmentFlags *flags)
const GrVkFramebuffer * getFramebuffer(bool withResolve, bool withStencil, SelfDependencyFlags selfDepFlags, LoadFromResolve)
GrVkImage * colorAttachment() const
GrBackendFormat backendFormat() const override
void onRelease() override
GrVkRenderTarget(GrVkGpu *gpu, SkISize dimensions, sk_sp< GrVkImage > colorAttachment, sk_sp< GrVkImage > resolveImage, CreateType createType, std::string_view label)
GrVkImage * resolveAttachment() const
GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle(bool withResolve, bool withStencil, SelfDependencyFlags selfDepFlags, LoadFromResolve)
static sk_sp< GrVkRenderTarget > MakeSecondaryCBRenderTarget(GrVkGpu *, SkISize, const GrVkDrawableInfo &vkInfo)
static sk_sp< GrVkRenderTarget > MakeWrappedRenderTarget(GrVkGpu *, SkISize, int sampleCnt, const GrVkImageInfo &, sk_sp< skgpu::MutableTextureState >)
const GrVkRenderPass * getSimpleRenderPass(bool withResolve, bool withStencil, SelfDependencyFlags selfDepFlags, LoadFromResolve)
const GrVkRenderPass * findCompatibleRenderPass(GrVkRenderTarget *target, CompatibleRPHandle *compatibleHandle, bool withResolve, bool withStencil, SelfDependencyFlags selfDepFlags, LoadFromResolve)
const GrVkRenderPass * findCompatibleExternalRenderPass(VkRenderPass, uint32_t colorAttachmentIndex)
static GrVkSecondaryCommandBuffer * Create(GrVkGpu *gpu, GrVkCommandPool *cmdPool)
T * get() const
Definition: SkRefCnt.h:303
T * release()
Definition: SkRefCnt.h:324
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
FlutterSemanticsFlag flags
uint32_t uint32_t * format
SK_API bool AsVkFormat(const GrBackendFormat &, VkFormat *)
SK_API GrBackendRenderTarget MakeVk(int width, int height, const GrVkImageInfo &)
SK_API MutableTextureState MakeVulkan(VkImageLayout layout, uint32_t queueFamilyIndex)
Protected
Definition: GpuTypes.h:61
Definition: ref_ptr.h:256
VkFormat fFormat
Definition: GrVkTypes.h:88
uint32_t fColorAttachmentIndex
Definition: GrVkTypes.h:86
VkRenderPass fCompatibleRenderPass
Definition: GrVkTypes.h:87
VkCommandBuffer fSecondaryCommandBuffer
Definition: GrVkTypes.h:85
Definition: SkSize.h:16
@ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
Definition: vulkan_core.h:1333
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
Definition: vulkan_core.h:2353
@ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
Definition: vulkan_core.h:2359
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
Definition: vulkan_core.h:2356
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
Definition: vulkan_core.h:2352
#define VK_NULL_HANDLE
Definition: vulkan_core.h:46
VkFormat
Definition: vulkan_core.h:1458
#define VK_QUEUE_FAMILY_IGNORED
Definition: vulkan_core.h:127