1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanResourceProvider.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/MutableTextureState.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/BackendTexture.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanMutableTextureState.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Buffer.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ComputePipeline.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/GraphicsPipeline.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RenderPassDesc.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Sampler.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Texture.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanBuffer.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanCommandBuffer.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanDescriptorPool.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanDescriptorSet.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanFramebuffer.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphicsPipeline.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteTypesPriv.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanRenderPass.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanSampler.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanSharedContext.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanTexture.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanYcbcrConversion.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanMemory.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLCompiler.h"
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanUtilsPriv.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include <android/hardware_buffer.h>
39*c8dee2aaSAndroid Build Coastguard Worker #endif
40*c8dee2aaSAndroid Build Coastguard Worker
41*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker constexpr int kMaxNumberOfCachedBufferDescSets = 1024;
44*c8dee2aaSAndroid Build Coastguard Worker
VulkanResourceProvider(SharedContext * sharedContext,SingleOwner * singleOwner,uint32_t recorderID,size_t resourceBudget,sk_sp<Buffer> intrinsicConstantUniformBuffer)45*c8dee2aaSAndroid Build Coastguard Worker VulkanResourceProvider::VulkanResourceProvider(SharedContext* sharedContext,
46*c8dee2aaSAndroid Build Coastguard Worker SingleOwner* singleOwner,
47*c8dee2aaSAndroid Build Coastguard Worker uint32_t recorderID,
48*c8dee2aaSAndroid Build Coastguard Worker size_t resourceBudget,
49*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> intrinsicConstantUniformBuffer)
50*c8dee2aaSAndroid Build Coastguard Worker : ResourceProvider(sharedContext, singleOwner, recorderID, resourceBudget)
51*c8dee2aaSAndroid Build Coastguard Worker , fIntrinsicUniformBuffer(std::move(intrinsicConstantUniformBuffer))
52*c8dee2aaSAndroid Build Coastguard Worker , fUniformBufferDescSetCache(kMaxNumberOfCachedBufferDescSets) {}
53*c8dee2aaSAndroid Build Coastguard Worker
~VulkanResourceProvider()54*c8dee2aaSAndroid Build Coastguard Worker VulkanResourceProvider::~VulkanResourceProvider() {
55*c8dee2aaSAndroid Build Coastguard Worker if (fPipelineCache != VK_NULL_HANDLE) {
56*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(this->vulkanSharedContext()->interface(),
57*c8dee2aaSAndroid Build Coastguard Worker DestroyPipelineCache(this->vulkanSharedContext()->device(),
58*c8dee2aaSAndroid Build Coastguard Worker fPipelineCache,
59*c8dee2aaSAndroid Build Coastguard Worker nullptr));
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker if (fMSAALoadVertShaderModule != VK_NULL_HANDLE) {
62*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(this->vulkanSharedContext()->interface(),
63*c8dee2aaSAndroid Build Coastguard Worker DestroyShaderModule(this->vulkanSharedContext()->device(),
64*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadVertShaderModule,
65*c8dee2aaSAndroid Build Coastguard Worker nullptr));
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker if (fMSAALoadFragShaderModule != VK_NULL_HANDLE) {
68*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(this->vulkanSharedContext()->interface(),
69*c8dee2aaSAndroid Build Coastguard Worker DestroyShaderModule(this->vulkanSharedContext()->device(),
70*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadFragShaderModule,
71*c8dee2aaSAndroid Build Coastguard Worker nullptr));
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker if (fMSAALoadPipelineLayout != VK_NULL_HANDLE) {
74*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(this->vulkanSharedContext()->interface(),
75*c8dee2aaSAndroid Build Coastguard Worker DestroyPipelineLayout(this->vulkanSharedContext()->device(),
76*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadPipelineLayout,
77*c8dee2aaSAndroid Build Coastguard Worker nullptr));
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
vulkanSharedContext() const81*c8dee2aaSAndroid Build Coastguard Worker const VulkanSharedContext* VulkanResourceProvider::vulkanSharedContext() const {
82*c8dee2aaSAndroid Build Coastguard Worker return static_cast<const VulkanSharedContext*>(fSharedContext);
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
onCreateWrappedTexture(const BackendTexture & texture)85*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Texture> VulkanResourceProvider::onCreateWrappedTexture(const BackendTexture& texture) {
86*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanYcbcrConversion> ycbcrConversion;
87*c8dee2aaSAndroid Build Coastguard Worker if (TextureInfos::GetVulkanYcbcrConversionInfo(texture.info()).isValid()) {
88*c8dee2aaSAndroid Build Coastguard Worker ycbcrConversion = this->findOrCreateCompatibleYcbcrConversion(
89*c8dee2aaSAndroid Build Coastguard Worker TextureInfos::GetVulkanYcbcrConversionInfo(texture.info()));
90*c8dee2aaSAndroid Build Coastguard Worker if (!ycbcrConversion) {
91*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker return VulkanTexture::MakeWrapped(this->vulkanSharedContext(),
96*c8dee2aaSAndroid Build Coastguard Worker texture.dimensions(),
97*c8dee2aaSAndroid Build Coastguard Worker texture.info(),
98*c8dee2aaSAndroid Build Coastguard Worker BackendTextures::GetMutableState(texture),
99*c8dee2aaSAndroid Build Coastguard Worker BackendTextures::GetVkImage(texture),
100*c8dee2aaSAndroid Build Coastguard Worker /*alloc=*/{} /*Skia does not own wrapped texture memory*/,
101*c8dee2aaSAndroid Build Coastguard Worker std::move(ycbcrConversion));
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker
refIntrinsicConstantBuffer() const104*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> VulkanResourceProvider::refIntrinsicConstantBuffer() const {
105*c8dee2aaSAndroid Build Coastguard Worker return fIntrinsicUniformBuffer;
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker
createGraphicsPipeline(const RuntimeEffectDictionary * runtimeDict,const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc,SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags)108*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GraphicsPipeline> VulkanResourceProvider::createGraphicsPipeline(
109*c8dee2aaSAndroid Build Coastguard Worker const RuntimeEffectDictionary* runtimeDict,
110*c8dee2aaSAndroid Build Coastguard Worker const GraphicsPipelineDesc& pipelineDesc,
111*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc,
112*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags) {
113*c8dee2aaSAndroid Build Coastguard Worker return VulkanGraphicsPipeline::Make(this,
114*c8dee2aaSAndroid Build Coastguard Worker runtimeDict,
115*c8dee2aaSAndroid Build Coastguard Worker pipelineDesc,
116*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc,
117*c8dee2aaSAndroid Build Coastguard Worker pipelineCreationFlags);
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker
createComputePipeline(const ComputePipelineDesc &)120*c8dee2aaSAndroid Build Coastguard Worker sk_sp<ComputePipeline> VulkanResourceProvider::createComputePipeline(const ComputePipelineDesc&) {
121*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker
createTexture(SkISize size,const TextureInfo & info,skgpu::Budgeted budgeted)124*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Texture> VulkanResourceProvider::createTexture(SkISize size,
125*c8dee2aaSAndroid Build Coastguard Worker const TextureInfo& info,
126*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted) {
127*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanYcbcrConversion> ycbcrConversion;
128*c8dee2aaSAndroid Build Coastguard Worker if (TextureInfos::GetVulkanYcbcrConversionInfo(info).isValid()) {
129*c8dee2aaSAndroid Build Coastguard Worker ycbcrConversion = this->findOrCreateCompatibleYcbcrConversion(
130*c8dee2aaSAndroid Build Coastguard Worker TextureInfos::GetVulkanYcbcrConversionInfo(info));
131*c8dee2aaSAndroid Build Coastguard Worker if (!ycbcrConversion) {
132*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker }
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker return VulkanTexture::Make(this->vulkanSharedContext(),
137*c8dee2aaSAndroid Build Coastguard Worker size,
138*c8dee2aaSAndroid Build Coastguard Worker info,
139*c8dee2aaSAndroid Build Coastguard Worker budgeted,
140*c8dee2aaSAndroid Build Coastguard Worker std::move(ycbcrConversion));
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
createBuffer(size_t size,BufferType type,AccessPattern accessPattern)143*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> VulkanResourceProvider::createBuffer(size_t size,
144*c8dee2aaSAndroid Build Coastguard Worker BufferType type,
145*c8dee2aaSAndroid Build Coastguard Worker AccessPattern accessPattern) {
146*c8dee2aaSAndroid Build Coastguard Worker return VulkanBuffer::Make(this->vulkanSharedContext(), size, type, accessPattern);
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker
createSampler(const SamplerDesc & samplerDesc)149*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Sampler> VulkanResourceProvider::createSampler(const SamplerDesc& samplerDesc) {
150*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanYcbcrConversion> ycbcrConversion = nullptr;
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker // Non-zero conversion information means the sampler utilizes a ycbcr conversion.
153*c8dee2aaSAndroid Build Coastguard Worker bool usesYcbcrConversion = (samplerDesc.desc() >> SamplerDesc::kImmutableSamplerInfoShift) != 0;
154*c8dee2aaSAndroid Build Coastguard Worker if (usesYcbcrConversion) {
155*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey ycbcrKey = VulkanYcbcrConversion::GetKeyFromSamplerDesc(samplerDesc);
156*c8dee2aaSAndroid Build Coastguard Worker if (Resource* resource = fResourceCache->findAndRefResource(ycbcrKey,
157*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes)) {
158*c8dee2aaSAndroid Build Coastguard Worker ycbcrConversion =
159*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanYcbcrConversion>(static_cast<VulkanYcbcrConversion*>(resource));
160*c8dee2aaSAndroid Build Coastguard Worker } else {
161*c8dee2aaSAndroid Build Coastguard Worker ycbcrConversion = VulkanYcbcrConversion::Make(
162*c8dee2aaSAndroid Build Coastguard Worker this->vulkanSharedContext(),
163*c8dee2aaSAndroid Build Coastguard Worker static_cast<uint32_t>(
164*c8dee2aaSAndroid Build Coastguard Worker samplerDesc.desc() >> SamplerDesc::kImmutableSamplerInfoShift),
165*c8dee2aaSAndroid Build Coastguard Worker (uint64_t)(samplerDesc.externalFormatMSBs()) << 32 | samplerDesc.format());
166*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(ycbcrConversion);
167*c8dee2aaSAndroid Build Coastguard Worker
168*c8dee2aaSAndroid Build Coastguard Worker ycbcrConversion->setKey(ycbcrKey);
169*c8dee2aaSAndroid Build Coastguard Worker fResourceCache->insertResource(ycbcrConversion.get());
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker }
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker return VulkanSampler::Make(this->vulkanSharedContext(),
174*c8dee2aaSAndroid Build Coastguard Worker samplerDesc,
175*c8dee2aaSAndroid Build Coastguard Worker std::move(ycbcrConversion));
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker
onCreateBackendTexture(SkISize dimensions,const TextureInfo & info)178*c8dee2aaSAndroid Build Coastguard Worker BackendTexture VulkanResourceProvider::onCreateBackendTexture(SkISize dimensions,
179*c8dee2aaSAndroid Build Coastguard Worker const TextureInfo& info) {
180*c8dee2aaSAndroid Build Coastguard Worker VulkanTextureInfo vkTexInfo;
181*c8dee2aaSAndroid Build Coastguard Worker if (!TextureInfos::GetVulkanTextureInfo(info, &vkTexInfo)) {
182*c8dee2aaSAndroid Build Coastguard Worker return {};
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker VulkanTexture::CreatedImageInfo createdTextureInfo;
185*c8dee2aaSAndroid Build Coastguard Worker if (!VulkanTexture::MakeVkImage(this->vulkanSharedContext(), dimensions, info,
186*c8dee2aaSAndroid Build Coastguard Worker &createdTextureInfo)) {
187*c8dee2aaSAndroid Build Coastguard Worker return {};
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker return BackendTextures::MakeVulkan(
190*c8dee2aaSAndroid Build Coastguard Worker dimensions,
191*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo,
192*c8dee2aaSAndroid Build Coastguard Worker skgpu::MutableTextureStates::GetVkImageLayout(createdTextureInfo.fMutableState.get()),
193*c8dee2aaSAndroid Build Coastguard Worker skgpu::MutableTextureStates::GetVkQueueFamilyIndex(
194*c8dee2aaSAndroid Build Coastguard Worker createdTextureInfo.fMutableState.get()),
195*c8dee2aaSAndroid Build Coastguard Worker createdTextureInfo.fImage,
196*c8dee2aaSAndroid Build Coastguard Worker createdTextureInfo.fMemoryAlloc);
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker
199*c8dee2aaSAndroid Build Coastguard Worker namespace {
build_desc_set_key(const SkSpan<DescriptorData> & requestedDescriptors)200*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey build_desc_set_key(const SkSpan<DescriptorData>& requestedDescriptors) {
201*c8dee2aaSAndroid Build Coastguard Worker static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();
202*c8dee2aaSAndroid Build Coastguard Worker
203*c8dee2aaSAndroid Build Coastguard Worker // The number of int32s needed for a key can depend on whether we use immutable samplers or not.
204*c8dee2aaSAndroid Build Coastguard Worker // So, accumulte key data while passing through to check for that quantity and simply copy
205*c8dee2aaSAndroid Build Coastguard Worker // into builder afterwards.
206*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<uint32_t> keyData (requestedDescriptors.size() + 1);
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker keyData.push_back(requestedDescriptors.size());
209*c8dee2aaSAndroid Build Coastguard Worker for (const DescriptorData& desc : requestedDescriptors) {
210*c8dee2aaSAndroid Build Coastguard Worker keyData.push_back(static_cast<uint8_t>(desc.fType) << 24 |
211*c8dee2aaSAndroid Build Coastguard Worker desc.fBindingIndex << 16 |
212*c8dee2aaSAndroid Build Coastguard Worker static_cast<uint16_t>(desc.fCount));
213*c8dee2aaSAndroid Build Coastguard Worker if (desc.fImmutableSampler) {
214*c8dee2aaSAndroid Build Coastguard Worker const VulkanSampler* sampler =
215*c8dee2aaSAndroid Build Coastguard Worker static_cast<const VulkanSampler*>(desc.fImmutableSampler);
216*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(sampler);
217*c8dee2aaSAndroid Build Coastguard Worker keyData.push_back_n(sampler->samplerDesc().asSpan().size(),
218*c8dee2aaSAndroid Build Coastguard Worker sampler->samplerDesc().asSpan().data());
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey key;
223*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey::Builder builder(&key, kType, keyData.size(), Shareable::kNo);
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < keyData.size(); i++) {
226*c8dee2aaSAndroid Build Coastguard Worker builder[i] = keyData[i];
227*c8dee2aaSAndroid Build Coastguard Worker }
228*c8dee2aaSAndroid Build Coastguard Worker
229*c8dee2aaSAndroid Build Coastguard Worker builder.finish();
230*c8dee2aaSAndroid Build Coastguard Worker return key;
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker
add_new_desc_set_to_cache(const VulkanSharedContext * context,const sk_sp<VulkanDescriptorPool> & pool,const GraphiteResourceKey & descSetKey,ResourceCache * resourceCache)233*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanDescriptorSet> add_new_desc_set_to_cache(const VulkanSharedContext* context,
234*c8dee2aaSAndroid Build Coastguard Worker const sk_sp<VulkanDescriptorPool>& pool,
235*c8dee2aaSAndroid Build Coastguard Worker const GraphiteResourceKey& descSetKey,
236*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache) {
237*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanDescriptorSet> descSet = VulkanDescriptorSet::Make(context, pool);
238*c8dee2aaSAndroid Build Coastguard Worker if (!descSet) {
239*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
240*c8dee2aaSAndroid Build Coastguard Worker }
241*c8dee2aaSAndroid Build Coastguard Worker descSet->setKey(descSetKey);
242*c8dee2aaSAndroid Build Coastguard Worker resourceCache->insertResource(descSet.get());
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker return descSet;
245*c8dee2aaSAndroid Build Coastguard Worker }
246*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
247*c8dee2aaSAndroid Build Coastguard Worker
findOrCreateDescriptorSet(SkSpan<DescriptorData> requestedDescriptors)248*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanDescriptorSet> VulkanResourceProvider::findOrCreateDescriptorSet(
249*c8dee2aaSAndroid Build Coastguard Worker SkSpan<DescriptorData> requestedDescriptors) {
250*c8dee2aaSAndroid Build Coastguard Worker if (requestedDescriptors.empty()) {
251*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
252*c8dee2aaSAndroid Build Coastguard Worker }
253*c8dee2aaSAndroid Build Coastguard Worker // Search for available descriptor sets by assembling a key based upon the set's structure.
254*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey key = build_desc_set_key(requestedDescriptors);
255*c8dee2aaSAndroid Build Coastguard Worker if (auto descSet = fResourceCache->findAndRefResource(key, skgpu::Budgeted::kYes)) {
256*c8dee2aaSAndroid Build Coastguard Worker // A non-null resource pointer indicates we have found an available descriptor set.
257*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<VulkanDescriptorSet>(static_cast<VulkanDescriptorSet*>(descSet));
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker
261*c8dee2aaSAndroid Build Coastguard Worker // If we did not find an existing avilable desc set, allocate sets with the appropriate layout
262*c8dee2aaSAndroid Build Coastguard Worker // and add them to the cache.
263*c8dee2aaSAndroid Build Coastguard Worker VkDescriptorSetLayout layout;
264*c8dee2aaSAndroid Build Coastguard Worker const VulkanSharedContext* context = this->vulkanSharedContext();
265*c8dee2aaSAndroid Build Coastguard Worker DescriptorDataToVkDescSetLayout(context, requestedDescriptors, &layout);
266*c8dee2aaSAndroid Build Coastguard Worker if (!layout) {
267*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
268*c8dee2aaSAndroid Build Coastguard Worker }
269*c8dee2aaSAndroid Build Coastguard Worker auto pool = VulkanDescriptorPool::Make(context, requestedDescriptors, layout);
270*c8dee2aaSAndroid Build Coastguard Worker if (!pool) {
271*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(context->interface(), DestroyDescriptorSetLayout(context->device(),
272*c8dee2aaSAndroid Build Coastguard Worker layout,
273*c8dee2aaSAndroid Build Coastguard Worker nullptr));
274*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
275*c8dee2aaSAndroid Build Coastguard Worker }
276*c8dee2aaSAndroid Build Coastguard Worker
277*c8dee2aaSAndroid Build Coastguard Worker // Start with allocating one descriptor set. If one cannot be successfully created, then we can
278*c8dee2aaSAndroid Build Coastguard Worker // return early before attempting to allocate more. Storing a ptr to the first set also
279*c8dee2aaSAndroid Build Coastguard Worker // allows us to return that later without having to perform a find operation on the cache once
280*c8dee2aaSAndroid Build Coastguard Worker // all the sets are added.
281*c8dee2aaSAndroid Build Coastguard Worker auto firstDescSet =
282*c8dee2aaSAndroid Build Coastguard Worker add_new_desc_set_to_cache(context, pool, key, fResourceCache.get());
283*c8dee2aaSAndroid Build Coastguard Worker if (!firstDescSet) {
284*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
285*c8dee2aaSAndroid Build Coastguard Worker }
286*c8dee2aaSAndroid Build Coastguard Worker
287*c8dee2aaSAndroid Build Coastguard Worker // Continue to allocate & cache the maximum number of sets so they can be easily accessed as
288*c8dee2aaSAndroid Build Coastguard Worker // they're needed.
289*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < VulkanDescriptorPool::kMaxNumSets ; i++) {
290*c8dee2aaSAndroid Build Coastguard Worker auto descSet =
291*c8dee2aaSAndroid Build Coastguard Worker add_new_desc_set_to_cache(context, pool, key, fResourceCache.get());
292*c8dee2aaSAndroid Build Coastguard Worker if (!descSet) {
293*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Descriptor set allocation %d of %d was unsuccessful; no more sets will be"
294*c8dee2aaSAndroid Build Coastguard Worker "allocated from this pool.", i, VulkanDescriptorPool::kMaxNumSets);
295*c8dee2aaSAndroid Build Coastguard Worker break;
296*c8dee2aaSAndroid Build Coastguard Worker }
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker return firstDescSet;
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker namespace {
303*c8dee2aaSAndroid Build Coastguard Worker
make_ubo_bind_group_key(SkSpan<DescriptorData> requestedDescriptors,SkSpan<BindBufferInfo> bindUniformBufferInfo)304*c8dee2aaSAndroid Build Coastguard Worker VulkanResourceProvider::UniformBindGroupKey make_ubo_bind_group_key(
305*c8dee2aaSAndroid Build Coastguard Worker SkSpan<DescriptorData> requestedDescriptors,
306*c8dee2aaSAndroid Build Coastguard Worker SkSpan<BindBufferInfo> bindUniformBufferInfo) {
307*c8dee2aaSAndroid Build Coastguard Worker VulkanResourceProvider::UniformBindGroupKey uniqueKey;
308*c8dee2aaSAndroid Build Coastguard Worker {
309*c8dee2aaSAndroid Build Coastguard Worker // Each entry in the bind group needs 2 uint32_t in the key:
310*c8dee2aaSAndroid Build Coastguard Worker // - buffer's unique ID: 32 bits.
311*c8dee2aaSAndroid Build Coastguard Worker // - buffer's binding size: 32 bits.
312*c8dee2aaSAndroid Build Coastguard Worker // We need total of 4 entries in the uniform buffer bind group.
313*c8dee2aaSAndroid Build Coastguard Worker // Unused entries will be assigned zero values.
314*c8dee2aaSAndroid Build Coastguard Worker VulkanResourceProvider::UniformBindGroupKey::Builder builder(&uniqueKey);
315*c8dee2aaSAndroid Build Coastguard Worker
316*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < VulkanGraphicsPipeline::kNumUniformBuffers; ++i) {
317*c8dee2aaSAndroid Build Coastguard Worker builder[2 * i] = 0;
318*c8dee2aaSAndroid Build Coastguard Worker builder[2 * i + 1] = 0;
319*c8dee2aaSAndroid Build Coastguard Worker }
320*c8dee2aaSAndroid Build Coastguard Worker
321*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < requestedDescriptors.size(); ++i) {
322*c8dee2aaSAndroid Build Coastguard Worker int descriptorBindingIndex = requestedDescriptors[i].fBindingIndex;
323*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) < bindUniformBufferInfo.size());
324*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) <
325*c8dee2aaSAndroid Build Coastguard Worker VulkanGraphicsPipeline::kNumUniformBuffers);
326*c8dee2aaSAndroid Build Coastguard Worker const auto& bindInfo = bindUniformBufferInfo[descriptorBindingIndex];
327*c8dee2aaSAndroid Build Coastguard Worker const VulkanBuffer* boundBuffer = static_cast<const VulkanBuffer*>(bindInfo.fBuffer);
328*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(boundBuffer);
329*c8dee2aaSAndroid Build Coastguard Worker builder[2 * descriptorBindingIndex] = boundBuffer->uniqueID().asUInt();
330*c8dee2aaSAndroid Build Coastguard Worker builder[2 * descriptorBindingIndex + 1] = bindInfo.fSize;
331*c8dee2aaSAndroid Build Coastguard Worker }
332*c8dee2aaSAndroid Build Coastguard Worker
333*c8dee2aaSAndroid Build Coastguard Worker builder.finish();
334*c8dee2aaSAndroid Build Coastguard Worker }
335*c8dee2aaSAndroid Build Coastguard Worker
336*c8dee2aaSAndroid Build Coastguard Worker return uniqueKey;
337*c8dee2aaSAndroid Build Coastguard Worker }
338*c8dee2aaSAndroid Build Coastguard Worker
update_uniform_descriptor_set(SkSpan<DescriptorData> requestedDescriptors,SkSpan<BindBufferInfo> bindUniformBufferInfo,VkDescriptorSet descSet,const VulkanSharedContext * sharedContext)339*c8dee2aaSAndroid Build Coastguard Worker void update_uniform_descriptor_set(SkSpan<DescriptorData> requestedDescriptors,
340*c8dee2aaSAndroid Build Coastguard Worker SkSpan<BindBufferInfo> bindUniformBufferInfo,
341*c8dee2aaSAndroid Build Coastguard Worker VkDescriptorSet descSet,
342*c8dee2aaSAndroid Build Coastguard Worker const VulkanSharedContext* sharedContext) {
343*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < requestedDescriptors.size(); i++) {
344*c8dee2aaSAndroid Build Coastguard Worker int descriptorBindingIndex = requestedDescriptors[i].fBindingIndex;
345*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) < bindUniformBufferInfo.size());
346*c8dee2aaSAndroid Build Coastguard Worker const auto& bindInfo = bindUniformBufferInfo[descriptorBindingIndex];
347*c8dee2aaSAndroid Build Coastguard Worker if (bindInfo.fBuffer) {
348*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_DEBUG)
349*c8dee2aaSAndroid Build Coastguard Worker static uint64_t maxBufferRange =
350*c8dee2aaSAndroid Build Coastguard Worker sharedContext->caps()->storageBufferSupport()
351*c8dee2aaSAndroid Build Coastguard Worker ? sharedContext->vulkanCaps().maxStorageBufferRange()
352*c8dee2aaSAndroid Build Coastguard Worker : sharedContext->vulkanCaps().maxUniformBufferRange();
353*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(bindInfo.fSize <= maxBufferRange);
354*c8dee2aaSAndroid Build Coastguard Worker #endif
355*c8dee2aaSAndroid Build Coastguard Worker VkDescriptorBufferInfo bufferInfo;
356*c8dee2aaSAndroid Build Coastguard Worker memset(&bufferInfo, 0, sizeof(VkDescriptorBufferInfo));
357*c8dee2aaSAndroid Build Coastguard Worker auto vulkanBuffer = static_cast<const VulkanBuffer*>(bindInfo.fBuffer);
358*c8dee2aaSAndroid Build Coastguard Worker bufferInfo.buffer = vulkanBuffer->vkBuffer();
359*c8dee2aaSAndroid Build Coastguard Worker bufferInfo.offset = 0; // We always use dynamic ubos so we set the base offset to 0
360*c8dee2aaSAndroid Build Coastguard Worker bufferInfo.range = bindInfo.fSize;
361*c8dee2aaSAndroid Build Coastguard Worker
362*c8dee2aaSAndroid Build Coastguard Worker VkWriteDescriptorSet writeInfo;
363*c8dee2aaSAndroid Build Coastguard Worker memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
364*c8dee2aaSAndroid Build Coastguard Worker writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
365*c8dee2aaSAndroid Build Coastguard Worker writeInfo.pNext = nullptr;
366*c8dee2aaSAndroid Build Coastguard Worker writeInfo.dstSet = descSet;
367*c8dee2aaSAndroid Build Coastguard Worker writeInfo.dstBinding = descriptorBindingIndex;
368*c8dee2aaSAndroid Build Coastguard Worker writeInfo.dstArrayElement = 0;
369*c8dee2aaSAndroid Build Coastguard Worker writeInfo.descriptorCount = requestedDescriptors[i].fCount;
370*c8dee2aaSAndroid Build Coastguard Worker writeInfo.descriptorType = DsTypeEnumToVkDs(requestedDescriptors[i].fType);
371*c8dee2aaSAndroid Build Coastguard Worker writeInfo.pImageInfo = nullptr;
372*c8dee2aaSAndroid Build Coastguard Worker writeInfo.pBufferInfo = &bufferInfo;
373*c8dee2aaSAndroid Build Coastguard Worker writeInfo.pTexelBufferView = nullptr;
374*c8dee2aaSAndroid Build Coastguard Worker
375*c8dee2aaSAndroid Build Coastguard Worker // TODO(b/293925059): Migrate to updating all the uniform descriptors with one driver
376*c8dee2aaSAndroid Build Coastguard Worker // call. Calling UpdateDescriptorSets once to encapsulate updates to all uniform
377*c8dee2aaSAndroid Build Coastguard Worker // descriptors would be ideal, but that led to issues with draws where all the UBOs
378*c8dee2aaSAndroid Build Coastguard Worker // within that set would unexpectedly be assigned the same offset. Updating them one at
379*c8dee2aaSAndroid Build Coastguard Worker // a time within this loop works in the meantime but is suboptimal.
380*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(sharedContext->interface(),
381*c8dee2aaSAndroid Build Coastguard Worker UpdateDescriptorSets(sharedContext->device(),
382*c8dee2aaSAndroid Build Coastguard Worker /*descriptorWriteCount=*/1,
383*c8dee2aaSAndroid Build Coastguard Worker &writeInfo,
384*c8dee2aaSAndroid Build Coastguard Worker /*descriptorCopyCount=*/0,
385*c8dee2aaSAndroid Build Coastguard Worker /*pDescriptorCopies=*/nullptr));
386*c8dee2aaSAndroid Build Coastguard Worker }
387*c8dee2aaSAndroid Build Coastguard Worker }
388*c8dee2aaSAndroid Build Coastguard Worker }
389*c8dee2aaSAndroid Build Coastguard Worker
390*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
391*c8dee2aaSAndroid Build Coastguard Worker
findOrCreateUniformBuffersDescriptorSet(SkSpan<DescriptorData> requestedDescriptors,SkSpan<BindBufferInfo> bindUniformBufferInfo)392*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanDescriptorSet> VulkanResourceProvider::findOrCreateUniformBuffersDescriptorSet(
393*c8dee2aaSAndroid Build Coastguard Worker SkSpan<DescriptorData> requestedDescriptors,
394*c8dee2aaSAndroid Build Coastguard Worker SkSpan<BindBufferInfo> bindUniformBufferInfo) {
395*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(requestedDescriptors.size() <= VulkanGraphicsPipeline::kNumUniformBuffers);
396*c8dee2aaSAndroid Build Coastguard Worker
397*c8dee2aaSAndroid Build Coastguard Worker auto key = make_ubo_bind_group_key(requestedDescriptors, bindUniformBufferInfo);
398*c8dee2aaSAndroid Build Coastguard Worker auto* existingDescSet = fUniformBufferDescSetCache.find(key);
399*c8dee2aaSAndroid Build Coastguard Worker if (existingDescSet) {
400*c8dee2aaSAndroid Build Coastguard Worker return *existingDescSet;
401*c8dee2aaSAndroid Build Coastguard Worker }
402*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanDescriptorSet> newDS = this->findOrCreateDescriptorSet(requestedDescriptors);
403*c8dee2aaSAndroid Build Coastguard Worker if (!newDS) {
404*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
405*c8dee2aaSAndroid Build Coastguard Worker }
406*c8dee2aaSAndroid Build Coastguard Worker
407*c8dee2aaSAndroid Build Coastguard Worker update_uniform_descriptor_set(requestedDescriptors,
408*c8dee2aaSAndroid Build Coastguard Worker bindUniformBufferInfo,
409*c8dee2aaSAndroid Build Coastguard Worker *newDS->descriptorSet(),
410*c8dee2aaSAndroid Build Coastguard Worker this->vulkanSharedContext());
411*c8dee2aaSAndroid Build Coastguard Worker return *fUniformBufferDescSetCache.insert(key, newDS);
412*c8dee2aaSAndroid Build Coastguard Worker }
413*c8dee2aaSAndroid Build Coastguard Worker
414*c8dee2aaSAndroid Build Coastguard Worker
findOrCreateRenderPassWithKnownKey(const RenderPassDesc & renderPassDesc,bool compatibleOnly,const GraphiteResourceKey & rpKey)415*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanRenderPass> VulkanResourceProvider::findOrCreateRenderPassWithKnownKey(
416*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc,
417*c8dee2aaSAndroid Build Coastguard Worker bool compatibleOnly,
418*c8dee2aaSAndroid Build Coastguard Worker const GraphiteResourceKey& rpKey) {
419*c8dee2aaSAndroid Build Coastguard Worker if (Resource* resource =
420*c8dee2aaSAndroid Build Coastguard Worker fResourceCache->findAndRefResource(rpKey, skgpu::Budgeted::kYes)) {
421*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<VulkanRenderPass>(static_cast<VulkanRenderPass*>(resource));
422*c8dee2aaSAndroid Build Coastguard Worker }
423*c8dee2aaSAndroid Build Coastguard Worker
424*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanRenderPass> renderPass =
425*c8dee2aaSAndroid Build Coastguard Worker VulkanRenderPass::MakeRenderPass(this->vulkanSharedContext(),
426*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc,
427*c8dee2aaSAndroid Build Coastguard Worker compatibleOnly);
428*c8dee2aaSAndroid Build Coastguard Worker if (!renderPass) {
429*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
430*c8dee2aaSAndroid Build Coastguard Worker }
431*c8dee2aaSAndroid Build Coastguard Worker
432*c8dee2aaSAndroid Build Coastguard Worker renderPass->setKey(rpKey);
433*c8dee2aaSAndroid Build Coastguard Worker fResourceCache->insertResource(renderPass.get());
434*c8dee2aaSAndroid Build Coastguard Worker
435*c8dee2aaSAndroid Build Coastguard Worker return renderPass;
436*c8dee2aaSAndroid Build Coastguard Worker }
437*c8dee2aaSAndroid Build Coastguard Worker
findOrCreateRenderPass(const RenderPassDesc & renderPassDesc,bool compatibleOnly)438*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanRenderPass> VulkanResourceProvider::findOrCreateRenderPass(
439*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc, bool compatibleOnly) {
440*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey rpKey = VulkanRenderPass::MakeRenderPassKey(renderPassDesc, compatibleOnly);
441*c8dee2aaSAndroid Build Coastguard Worker
442*c8dee2aaSAndroid Build Coastguard Worker return this->findOrCreateRenderPassWithKnownKey(renderPassDesc, compatibleOnly, rpKey);
443*c8dee2aaSAndroid Build Coastguard Worker }
444*c8dee2aaSAndroid Build Coastguard Worker
pipelineCache()445*c8dee2aaSAndroid Build Coastguard Worker VkPipelineCache VulkanResourceProvider::pipelineCache() {
446*c8dee2aaSAndroid Build Coastguard Worker if (fPipelineCache == VK_NULL_HANDLE) {
447*c8dee2aaSAndroid Build Coastguard Worker VkPipelineCacheCreateInfo createInfo;
448*c8dee2aaSAndroid Build Coastguard Worker memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
449*c8dee2aaSAndroid Build Coastguard Worker createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
450*c8dee2aaSAndroid Build Coastguard Worker createInfo.pNext = nullptr;
451*c8dee2aaSAndroid Build Coastguard Worker createInfo.flags = 0;
452*c8dee2aaSAndroid Build Coastguard Worker createInfo.initialDataSize = 0;
453*c8dee2aaSAndroid Build Coastguard Worker createInfo.pInitialData = nullptr;
454*c8dee2aaSAndroid Build Coastguard Worker VkResult result;
455*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL_RESULT(this->vulkanSharedContext(),
456*c8dee2aaSAndroid Build Coastguard Worker result,
457*c8dee2aaSAndroid Build Coastguard Worker CreatePipelineCache(this->vulkanSharedContext()->device(),
458*c8dee2aaSAndroid Build Coastguard Worker &createInfo,
459*c8dee2aaSAndroid Build Coastguard Worker nullptr,
460*c8dee2aaSAndroid Build Coastguard Worker &fPipelineCache));
461*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != result) {
462*c8dee2aaSAndroid Build Coastguard Worker fPipelineCache = VK_NULL_HANDLE;
463*c8dee2aaSAndroid Build Coastguard Worker }
464*c8dee2aaSAndroid Build Coastguard Worker }
465*c8dee2aaSAndroid Build Coastguard Worker return fPipelineCache;
466*c8dee2aaSAndroid Build Coastguard Worker }
467*c8dee2aaSAndroid Build Coastguard Worker
createFramebuffer(const VulkanSharedContext * context,const skia_private::TArray<VkImageView> & attachmentViews,const VulkanRenderPass & renderPass,const int width,const int height)468*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanFramebuffer> VulkanResourceProvider::createFramebuffer(
469*c8dee2aaSAndroid Build Coastguard Worker const VulkanSharedContext* context,
470*c8dee2aaSAndroid Build Coastguard Worker const skia_private::TArray<VkImageView>& attachmentViews,
471*c8dee2aaSAndroid Build Coastguard Worker const VulkanRenderPass& renderPass,
472*c8dee2aaSAndroid Build Coastguard Worker const int width,
473*c8dee2aaSAndroid Build Coastguard Worker const int height) {
474*c8dee2aaSAndroid Build Coastguard Worker // TODO: Consider caching these in the future. If we pursue that, it may make more sense to
475*c8dee2aaSAndroid Build Coastguard Worker // use a compatible renderpass rather than a full one to make each frame buffer more versatile.
476*c8dee2aaSAndroid Build Coastguard Worker VkFramebufferCreateInfo framebufferInfo;
477*c8dee2aaSAndroid Build Coastguard Worker memset(&framebufferInfo, 0, sizeof(VkFramebufferCreateInfo));
478*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
479*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.pNext = nullptr;
480*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.flags = 0;
481*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.renderPass = renderPass.renderPass();
482*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.attachmentCount = attachmentViews.size();
483*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.pAttachments = attachmentViews.begin();
484*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.width = width;
485*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.height = height;
486*c8dee2aaSAndroid Build Coastguard Worker framebufferInfo.layers = 1;
487*c8dee2aaSAndroid Build Coastguard Worker return VulkanFramebuffer::Make(context, framebufferInfo);
488*c8dee2aaSAndroid Build Coastguard Worker }
489*c8dee2aaSAndroid Build Coastguard Worker
onDeleteBackendTexture(const BackendTexture & texture)490*c8dee2aaSAndroid Build Coastguard Worker void VulkanResourceProvider::onDeleteBackendTexture(const BackendTexture& texture) {
491*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(texture.isValid());
492*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(texture.backend() == BackendApi::kVulkan);
493*c8dee2aaSAndroid Build Coastguard Worker
494*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(this->vulkanSharedContext()->interface(),
495*c8dee2aaSAndroid Build Coastguard Worker DestroyImage(this->vulkanSharedContext()->device(),
496*c8dee2aaSAndroid Build Coastguard Worker BackendTextures::GetVkImage(texture),
497*c8dee2aaSAndroid Build Coastguard Worker /*VkAllocationCallbacks=*/nullptr));
498*c8dee2aaSAndroid Build Coastguard Worker
499*c8dee2aaSAndroid Build Coastguard Worker VulkanAlloc alloc = BackendTextures::GetMemoryAlloc(texture);
500*c8dee2aaSAndroid Build Coastguard Worker // Free the image memory used for the BackendTexture's VkImage.
501*c8dee2aaSAndroid Build Coastguard Worker //
502*c8dee2aaSAndroid Build Coastguard Worker // How we do this is dependent upon on how the image was allocated (via the memory allocator or
503*c8dee2aaSAndroid Build Coastguard Worker // with a direct call to the Vulkan driver) . If the VulkanAlloc's fBackendMemory is != 0, then
504*c8dee2aaSAndroid Build Coastguard Worker // that means the allocator was used. Otherwise, a direct driver call was used and we should
505*c8dee2aaSAndroid Build Coastguard Worker // free the VkDeviceMemory (fMemory).
506*c8dee2aaSAndroid Build Coastguard Worker if (alloc.fBackendMemory) {
507*c8dee2aaSAndroid Build Coastguard Worker skgpu::VulkanMemory::FreeImageMemory(this->vulkanSharedContext()->memoryAllocator(), alloc);
508*c8dee2aaSAndroid Build Coastguard Worker } else {
509*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(alloc.fMemory != VK_NULL_HANDLE);
510*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(this->vulkanSharedContext()->interface(),
511*c8dee2aaSAndroid Build Coastguard Worker FreeMemory(this->vulkanSharedContext()->device(), alloc.fMemory, nullptr));
512*c8dee2aaSAndroid Build Coastguard Worker }
513*c8dee2aaSAndroid Build Coastguard Worker }
514*c8dee2aaSAndroid Build Coastguard Worker
findOrCreateCompatibleYcbcrConversion(const VulkanYcbcrConversionInfo & ycbcrInfo) const515*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanYcbcrConversion> VulkanResourceProvider::findOrCreateCompatibleYcbcrConversion(
516*c8dee2aaSAndroid Build Coastguard Worker const VulkanYcbcrConversionInfo& ycbcrInfo) const {
517*c8dee2aaSAndroid Build Coastguard Worker if (!ycbcrInfo.isValid()) {
518*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
519*c8dee2aaSAndroid Build Coastguard Worker }
520*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey ycbcrConversionKey =
521*c8dee2aaSAndroid Build Coastguard Worker VulkanYcbcrConversion::MakeYcbcrConversionKey(this->vulkanSharedContext(), ycbcrInfo);
522*c8dee2aaSAndroid Build Coastguard Worker
523*c8dee2aaSAndroid Build Coastguard Worker if (Resource* resource = fResourceCache->findAndRefResource(ycbcrConversionKey,
524*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes)) {
525*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<VulkanYcbcrConversion>(static_cast<VulkanYcbcrConversion*>(resource));
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker
528*c8dee2aaSAndroid Build Coastguard Worker auto ycbcrConversion = VulkanYcbcrConversion::Make(this->vulkanSharedContext(), ycbcrInfo);
529*c8dee2aaSAndroid Build Coastguard Worker if (!ycbcrConversion) {
530*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
531*c8dee2aaSAndroid Build Coastguard Worker }
532*c8dee2aaSAndroid Build Coastguard Worker
533*c8dee2aaSAndroid Build Coastguard Worker ycbcrConversion->setKey(ycbcrConversionKey);
534*c8dee2aaSAndroid Build Coastguard Worker fResourceCache->insertResource(ycbcrConversion.get());
535*c8dee2aaSAndroid Build Coastguard Worker
536*c8dee2aaSAndroid Build Coastguard Worker return ycbcrConversion;
537*c8dee2aaSAndroid Build Coastguard Worker }
538*c8dee2aaSAndroid Build Coastguard Worker
findOrCreateLoadMSAAPipeline(const RenderPassDesc & renderPassDesc)539*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanGraphicsPipeline> VulkanResourceProvider::findOrCreateLoadMSAAPipeline(
540*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc) {
541*c8dee2aaSAndroid Build Coastguard Worker
542*c8dee2aaSAndroid Build Coastguard Worker if (!renderPassDesc.fColorResolveAttachment.fTextureInfo.isValid() ||
543*c8dee2aaSAndroid Build Coastguard Worker !renderPassDesc.fColorAttachment.fTextureInfo.isValid()) {
544*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_E("Loading MSAA from resolve texture requires valid color & resolve attachment");
545*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
546*c8dee2aaSAndroid Build Coastguard Worker }
547*c8dee2aaSAndroid Build Coastguard Worker
548*c8dee2aaSAndroid Build Coastguard Worker // Check to see if we already have a suitable pipeline that we can use.
549*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey renderPassKey =
550*c8dee2aaSAndroid Build Coastguard Worker VulkanRenderPass::MakeRenderPassKey(renderPassDesc, /*compatibleOnly=*/true);
551*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fLoadMSAAPipelines.size(); i++) {
552*c8dee2aaSAndroid Build Coastguard Worker if (renderPassKey == fLoadMSAAPipelines.at(i).first) {
553*c8dee2aaSAndroid Build Coastguard Worker return fLoadMSAAPipelines.at(i).second;
554*c8dee2aaSAndroid Build Coastguard Worker }
555*c8dee2aaSAndroid Build Coastguard Worker }
556*c8dee2aaSAndroid Build Coastguard Worker
557*c8dee2aaSAndroid Build Coastguard Worker // If any of the load MSAA pipeline creation structures are null then we need to initialize
558*c8dee2aaSAndroid Build Coastguard Worker // those before proceeding. If the creation of one of them fails, all are assigned to null, so
559*c8dee2aaSAndroid Build Coastguard Worker // we only need to check one of the structures.
560*c8dee2aaSAndroid Build Coastguard Worker if (fMSAALoadVertShaderModule == VK_NULL_HANDLE) {
561*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fMSAALoadFragShaderModule == VK_NULL_HANDLE &&
562*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadPipelineLayout == VK_NULL_HANDLE);
563*c8dee2aaSAndroid Build Coastguard Worker if (!VulkanGraphicsPipeline::InitializeMSAALoadPipelineStructs(
564*c8dee2aaSAndroid Build Coastguard Worker this->vulkanSharedContext(),
565*c8dee2aaSAndroid Build Coastguard Worker &fMSAALoadVertShaderModule,
566*c8dee2aaSAndroid Build Coastguard Worker &fMSAALoadFragShaderModule,
567*c8dee2aaSAndroid Build Coastguard Worker &fMSAALoadShaderStageInfo[0],
568*c8dee2aaSAndroid Build Coastguard Worker &fMSAALoadPipelineLayout)) {
569*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_E("Failed to initialize MSAA load pipeline creation structure(s)");
570*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
571*c8dee2aaSAndroid Build Coastguard Worker }
572*c8dee2aaSAndroid Build Coastguard Worker }
573*c8dee2aaSAndroid Build Coastguard Worker
574*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanRenderPass> compatibleRenderPass =
575*c8dee2aaSAndroid Build Coastguard Worker this->findOrCreateRenderPassWithKnownKey(renderPassDesc,
576*c8dee2aaSAndroid Build Coastguard Worker /*compatibleOnly=*/true,
577*c8dee2aaSAndroid Build Coastguard Worker renderPassKey);
578*c8dee2aaSAndroid Build Coastguard Worker if (!compatibleRenderPass) {
579*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_E("Failed to make compatible render pass for loading MSAA");
580*c8dee2aaSAndroid Build Coastguard Worker }
581*c8dee2aaSAndroid Build Coastguard Worker
582*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanGraphicsPipeline> pipeline = VulkanGraphicsPipeline::MakeLoadMSAAPipeline(
583*c8dee2aaSAndroid Build Coastguard Worker this->vulkanSharedContext(),
584*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadVertShaderModule,
585*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadFragShaderModule,
586*c8dee2aaSAndroid Build Coastguard Worker &fMSAALoadShaderStageInfo[0],
587*c8dee2aaSAndroid Build Coastguard Worker fMSAALoadPipelineLayout,
588*c8dee2aaSAndroid Build Coastguard Worker compatibleRenderPass,
589*c8dee2aaSAndroid Build Coastguard Worker this->pipelineCache(),
590*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc.fColorAttachment.fTextureInfo);
591*c8dee2aaSAndroid Build Coastguard Worker
592*c8dee2aaSAndroid Build Coastguard Worker if (!pipeline) {
593*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_E("Failed to create MSAA load pipeline");
594*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
595*c8dee2aaSAndroid Build Coastguard Worker }
596*c8dee2aaSAndroid Build Coastguard Worker
597*c8dee2aaSAndroid Build Coastguard Worker fLoadMSAAPipelines.push_back(std::make_pair(renderPassKey, pipeline));
598*c8dee2aaSAndroid Build Coastguard Worker return pipeline;
599*c8dee2aaSAndroid Build Coastguard Worker }
600*c8dee2aaSAndroid Build Coastguard Worker
601*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
602*c8dee2aaSAndroid Build Coastguard Worker
onCreateBackendTexture(AHardwareBuffer * hardwareBuffer,bool isRenderable,bool isProtectedContent,SkISize dimensions,bool fromAndroidWindow) const603*c8dee2aaSAndroid Build Coastguard Worker BackendTexture VulkanResourceProvider::onCreateBackendTexture(AHardwareBuffer* hardwareBuffer,
604*c8dee2aaSAndroid Build Coastguard Worker bool isRenderable,
605*c8dee2aaSAndroid Build Coastguard Worker bool isProtectedContent,
606*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions,
607*c8dee2aaSAndroid Build Coastguard Worker bool fromAndroidWindow) const {
608*c8dee2aaSAndroid Build Coastguard Worker
609*c8dee2aaSAndroid Build Coastguard Worker const VulkanSharedContext* vkContext = this->vulkanSharedContext();
610*c8dee2aaSAndroid Build Coastguard Worker VkDevice device = vkContext->device();
611*c8dee2aaSAndroid Build Coastguard Worker const VulkanCaps& vkCaps = vkContext->vulkanCaps();
612*c8dee2aaSAndroid Build Coastguard Worker
613*c8dee2aaSAndroid Build Coastguard Worker VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
614*c8dee2aaSAndroid Build Coastguard Worker VkAndroidHardwareBufferPropertiesANDROID hwbProps;
615*c8dee2aaSAndroid Build Coastguard Worker if (!skgpu::GetAHardwareBufferProperties(
616*c8dee2aaSAndroid Build Coastguard Worker &hwbFormatProps, &hwbProps, vkContext->interface(), hardwareBuffer, device)) {
617*c8dee2aaSAndroid Build Coastguard Worker return {};
618*c8dee2aaSAndroid Build Coastguard Worker }
619*c8dee2aaSAndroid Build Coastguard Worker
620*c8dee2aaSAndroid Build Coastguard Worker bool importAsExternalFormat = hwbFormatProps.format == VK_FORMAT_UNDEFINED;
621*c8dee2aaSAndroid Build Coastguard Worker
622*c8dee2aaSAndroid Build Coastguard Worker // Start to assemble VulkanTextureInfo which is needed later on to create the VkImage but can
623*c8dee2aaSAndroid Build Coastguard Worker // sooner help us query VulkanCaps for certain format feature support.
624*c8dee2aaSAndroid Build Coastguard Worker // TODO: Allow client to pass in tiling mode. For external formats, this is required to be
625*c8dee2aaSAndroid Build Coastguard Worker // optimal. For AHB that have a known Vulkan format, we can query VulkanCaps to determine if
626*c8dee2aaSAndroid Build Coastguard Worker // optimal is a valid decision given the format features.
627*c8dee2aaSAndroid Build Coastguard Worker VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
628*c8dee2aaSAndroid Build Coastguard Worker VkImageCreateFlags imgCreateflags = isProtectedContent ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
629*c8dee2aaSAndroid Build Coastguard Worker VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
630*c8dee2aaSAndroid Build Coastguard Worker // When importing as an external format the image usage can only be VK_IMAGE_USAGE_SAMPLED_BIT.
631*c8dee2aaSAndroid Build Coastguard Worker if (!importAsExternalFormat) {
632*c8dee2aaSAndroid Build Coastguard Worker usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
633*c8dee2aaSAndroid Build Coastguard Worker if (isRenderable) {
634*c8dee2aaSAndroid Build Coastguard Worker // Renderable attachments can be used as input attachments if we are loading from MSAA.
635*c8dee2aaSAndroid Build Coastguard Worker usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
636*c8dee2aaSAndroid Build Coastguard Worker }
637*c8dee2aaSAndroid Build Coastguard Worker }
638*c8dee2aaSAndroid Build Coastguard Worker VulkanTextureInfo vkTexInfo { VK_SAMPLE_COUNT_1_BIT,
639*c8dee2aaSAndroid Build Coastguard Worker Mipmapped::kNo,
640*c8dee2aaSAndroid Build Coastguard Worker imgCreateflags,
641*c8dee2aaSAndroid Build Coastguard Worker hwbFormatProps.format,
642*c8dee2aaSAndroid Build Coastguard Worker tiling,
643*c8dee2aaSAndroid Build Coastguard Worker usageFlags,
644*c8dee2aaSAndroid Build Coastguard Worker VK_SHARING_MODE_EXCLUSIVE,
645*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_ASPECT_COLOR_BIT,
646*c8dee2aaSAndroid Build Coastguard Worker VulkanYcbcrConversionInfo() };
647*c8dee2aaSAndroid Build Coastguard Worker
648*c8dee2aaSAndroid Build Coastguard Worker if (isRenderable && (importAsExternalFormat || !vkCaps.isRenderable(vkTexInfo))) {
649*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Renderable texture requested from an AHardwareBuffer which uses a VkFormat "
650*c8dee2aaSAndroid Build Coastguard Worker "that Skia cannot render to (VkFormat: %d).\n", hwbFormatProps.format);
651*c8dee2aaSAndroid Build Coastguard Worker return {};
652*c8dee2aaSAndroid Build Coastguard Worker }
653*c8dee2aaSAndroid Build Coastguard Worker
654*c8dee2aaSAndroid Build Coastguard Worker if (!importAsExternalFormat && (!vkCaps.isTransferSrc(vkTexInfo) ||
655*c8dee2aaSAndroid Build Coastguard Worker !vkCaps.isTransferDst(vkTexInfo) ||
656*c8dee2aaSAndroid Build Coastguard Worker !vkCaps.isTexturable(vkTexInfo))) {
657*c8dee2aaSAndroid Build Coastguard Worker if (isRenderable) {
658*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("VkFormat %d is either unfamiliar to Skia or doesn't support the necessary"
659*c8dee2aaSAndroid Build Coastguard Worker " format features. Because a renerable texture was requested, we cannot "
660*c8dee2aaSAndroid Build Coastguard Worker "fall back to importing with an external format.\n", hwbFormatProps.format);
661*c8dee2aaSAndroid Build Coastguard Worker return {};
662*c8dee2aaSAndroid Build Coastguard Worker }
663*c8dee2aaSAndroid Build Coastguard Worker // If the VkFormat does not support the features we need, then import as an external format.
664*c8dee2aaSAndroid Build Coastguard Worker importAsExternalFormat = true;
665*c8dee2aaSAndroid Build Coastguard Worker // If we use VkExternalFormatANDROID with an externalFormat != 0, then format must =
666*c8dee2aaSAndroid Build Coastguard Worker // VK_FORMAT_UNDEFINED.
667*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fFormat = VK_FORMAT_UNDEFINED;
668*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
669*c8dee2aaSAndroid Build Coastguard Worker }
670*c8dee2aaSAndroid Build Coastguard Worker
671*c8dee2aaSAndroid Build Coastguard Worker VulkanYcbcrConversionInfo ycbcrInfo;
672*c8dee2aaSAndroid Build Coastguard Worker VkExternalFormatANDROID externalFormat;
673*c8dee2aaSAndroid Build Coastguard Worker externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
674*c8dee2aaSAndroid Build Coastguard Worker externalFormat.pNext = nullptr;
675*c8dee2aaSAndroid Build Coastguard Worker externalFormat.externalFormat = 0; // If this is zero it is as if we aren't using this struct.
676*c8dee2aaSAndroid Build Coastguard Worker if (importAsExternalFormat) {
677*c8dee2aaSAndroid Build Coastguard Worker GetYcbcrConversionInfoFromFormatProps(&ycbcrInfo, hwbFormatProps);
678*c8dee2aaSAndroid Build Coastguard Worker if (!ycbcrInfo.isValid()) {
679*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_W("Failed to create valid YCbCr conversion information from hardware buffer"
680*c8dee2aaSAndroid Build Coastguard Worker "format properties.\n");
681*c8dee2aaSAndroid Build Coastguard Worker return {};
682*c8dee2aaSAndroid Build Coastguard Worker }
683*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fYcbcrConversionInfo = ycbcrInfo;
684*c8dee2aaSAndroid Build Coastguard Worker externalFormat.externalFormat = hwbFormatProps.externalFormat;
685*c8dee2aaSAndroid Build Coastguard Worker }
686*c8dee2aaSAndroid Build Coastguard Worker const VkExternalMemoryImageCreateInfo externalMemoryImageInfo{
687*c8dee2aaSAndroid Build Coastguard Worker VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
688*c8dee2aaSAndroid Build Coastguard Worker &externalFormat, // pNext
689*c8dee2aaSAndroid Build Coastguard Worker VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
690*c8dee2aaSAndroid Build Coastguard Worker };
691*c8dee2aaSAndroid Build Coastguard Worker
692*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!(vkTexInfo.fFlags & VK_IMAGE_CREATE_PROTECTED_BIT) ||
693*c8dee2aaSAndroid Build Coastguard Worker fSharedContext->isProtected() == Protected::kYes);
694*c8dee2aaSAndroid Build Coastguard Worker
695*c8dee2aaSAndroid Build Coastguard Worker const VkImageCreateInfo imageCreateInfo = {
696*c8dee2aaSAndroid Build Coastguard Worker VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
697*c8dee2aaSAndroid Build Coastguard Worker &externalMemoryImageInfo, // pNext
698*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fFlags, // VkImageCreateFlags
699*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_TYPE_2D, // VkImageType
700*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fFormat, // VkFormat
701*c8dee2aaSAndroid Build Coastguard Worker { (uint32_t)dimensions.fWidth, (uint32_t)dimensions.fHeight, 1 }, // VkExtent3D
702*c8dee2aaSAndroid Build Coastguard Worker 1, // mipLevels
703*c8dee2aaSAndroid Build Coastguard Worker 1, // arrayLayers
704*c8dee2aaSAndroid Build Coastguard Worker VK_SAMPLE_COUNT_1_BIT, // samples
705*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fImageTiling, // VkImageTiling
706*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fImageUsageFlags, // VkImageUsageFlags
707*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo.fSharingMode, // VkSharingMode
708*c8dee2aaSAndroid Build Coastguard Worker 0, // queueFamilyCount
709*c8dee2aaSAndroid Build Coastguard Worker nullptr, // pQueueFamilyIndices
710*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
711*c8dee2aaSAndroid Build Coastguard Worker };
712*c8dee2aaSAndroid Build Coastguard Worker
713*c8dee2aaSAndroid Build Coastguard Worker VkResult result;
714*c8dee2aaSAndroid Build Coastguard Worker VkImage image;
715*c8dee2aaSAndroid Build Coastguard Worker result = VULKAN_CALL(vkContext->interface(),
716*c8dee2aaSAndroid Build Coastguard Worker CreateImage(device, &imageCreateInfo, nullptr, &image));
717*c8dee2aaSAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
718*c8dee2aaSAndroid Build Coastguard Worker return {};
719*c8dee2aaSAndroid Build Coastguard Worker }
720*c8dee2aaSAndroid Build Coastguard Worker
721*c8dee2aaSAndroid Build Coastguard Worker const VkPhysicalDeviceMemoryProperties2& phyDevMemProps =
722*c8dee2aaSAndroid Build Coastguard Worker vkContext->vulkanCaps().physicalDeviceMemoryProperties2();
723*c8dee2aaSAndroid Build Coastguard Worker VulkanAlloc alloc;
724*c8dee2aaSAndroid Build Coastguard Worker if (!AllocateAndBindImageMemory(&alloc, image, phyDevMemProps, hwbProps, hardwareBuffer,
725*c8dee2aaSAndroid Build Coastguard Worker vkContext->interface(), device)) {
726*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(vkContext->interface(), DestroyImage(device, image, nullptr));
727*c8dee2aaSAndroid Build Coastguard Worker return {};
728*c8dee2aaSAndroid Build Coastguard Worker }
729*c8dee2aaSAndroid Build Coastguard Worker
730*c8dee2aaSAndroid Build Coastguard Worker return BackendTextures::MakeVulkan(dimensions,
731*c8dee2aaSAndroid Build Coastguard Worker vkTexInfo,
732*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_LAYOUT_UNDEFINED,
733*c8dee2aaSAndroid Build Coastguard Worker VK_QUEUE_FAMILY_FOREIGN_EXT,
734*c8dee2aaSAndroid Build Coastguard Worker image,
735*c8dee2aaSAndroid Build Coastguard Worker alloc);
736*c8dee2aaSAndroid Build Coastguard Worker }
737*c8dee2aaSAndroid Build Coastguard Worker
738*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_BUILD_FOR_ANDROID
739*c8dee2aaSAndroid Build Coastguard Worker
740*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
741