1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSemaphore.h" 11cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h" 12cb93a386Sopenharmony_ci#include "include/gpu/GrContextOptions.h" 13cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 15cb93a386Sopenharmony_ci#include "src/core/SkCompressedDataUtils.h" 16cb93a386Sopenharmony_ci#include "src/core/SkConvertPixels.h" 17cb93a386Sopenharmony_ci#include "src/core/SkMipmap.h" 18cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 19cb93a386Sopenharmony_ci#include "src/core/SkUtils.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrBackendUtils.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrDataUtils.h" 22cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 23cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 24cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourceCacheAccess.h" 25cb93a386Sopenharmony_ci#include "src/gpu/GrNativeRect.h" 26cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h" 27cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 28cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 29cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 30cb93a386Sopenharmony_ci#include "src/gpu/GrThreadSafePipelineBuilder.h" 31cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h" 32cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkAMDMemoryAllocator.h" 33cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkBuffer.h" 34cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandBuffer.h" 35cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandPool.h" 36cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkFramebuffer.h" 37cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImage.h" 38cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkInterface.h" 39cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkMemory.h" 40cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkOpsRenderPass.h" 41cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipeline.h" 42cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipelineState.h" 43cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderPass.h" 44cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkResourceProvider.h" 45cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkSemaphore.h" 46cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkTexture.h" 47cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkTextureRenderTarget.h" 48cb93a386Sopenharmony_ci#include "src/image/SkImage_Gpu.h" 49cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h" 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci#include "include/gpu/vk/GrVkExtensions.h" 52cb93a386Sopenharmony_ci#include "include/gpu/vk/GrVkTypes.h" 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci#include <utility> 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X) 57cb93a386Sopenharmony_ci#define VK_CALL_RET(RET, X) GR_VK_CALL_RESULT(this, RET, X) 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ciconstexpr uint8_t ASTC_HEADER_SIZE = 16; 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_cisk_sp<GrGpu> GrVkGpu::Make(const GrVkBackendContext& backendContext, 62cb93a386Sopenharmony_ci const GrContextOptions& options, GrDirectContext* direct) { 63cb93a386Sopenharmony_ci if (backendContext.fInstance == VK_NULL_HANDLE || 64cb93a386Sopenharmony_ci backendContext.fPhysicalDevice == VK_NULL_HANDLE || 65cb93a386Sopenharmony_ci backendContext.fDevice == VK_NULL_HANDLE || 66cb93a386Sopenharmony_ci backendContext.fQueue == VK_NULL_HANDLE) { 67cb93a386Sopenharmony_ci return nullptr; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci if (!backendContext.fGetProc) { 70cb93a386Sopenharmony_ci return nullptr; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci PFN_vkEnumerateInstanceVersion localEnumerateInstanceVersion = 74cb93a386Sopenharmony_ci reinterpret_cast<PFN_vkEnumerateInstanceVersion>( 75cb93a386Sopenharmony_ci backendContext.fGetProc("vkEnumerateInstanceVersion", 76cb93a386Sopenharmony_ci VK_NULL_HANDLE, VK_NULL_HANDLE)); 77cb93a386Sopenharmony_ci uint32_t instanceVersion = 0; 78cb93a386Sopenharmony_ci if (!localEnumerateInstanceVersion) { 79cb93a386Sopenharmony_ci instanceVersion = VK_MAKE_VERSION(1, 0, 0); 80cb93a386Sopenharmony_ci } else { 81cb93a386Sopenharmony_ci VkResult err = localEnumerateInstanceVersion(&instanceVersion); 82cb93a386Sopenharmony_ci if (err) { 83cb93a386Sopenharmony_ci SkDebugf("Failed to enumerate instance version. Err: %d\n", err); 84cb93a386Sopenharmony_ci return nullptr; 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties = 89cb93a386Sopenharmony_ci reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>( 90cb93a386Sopenharmony_ci backendContext.fGetProc("vkGetPhysicalDeviceProperties", 91cb93a386Sopenharmony_ci backendContext.fInstance, 92cb93a386Sopenharmony_ci VK_NULL_HANDLE)); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci if (!localGetPhysicalDeviceProperties) { 95cb93a386Sopenharmony_ci return nullptr; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci VkPhysicalDeviceProperties physDeviceProperties; 98cb93a386Sopenharmony_ci localGetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &physDeviceProperties); 99cb93a386Sopenharmony_ci uint32_t physDevVersion = physDeviceProperties.apiVersion; 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci uint32_t apiVersion = backendContext.fMaxAPIVersion ? backendContext.fMaxAPIVersion 102cb93a386Sopenharmony_ci : instanceVersion; 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci instanceVersion = std::min(instanceVersion, apiVersion); 105cb93a386Sopenharmony_ci physDevVersion = std::min(physDevVersion, apiVersion); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci sk_sp<const GrVkInterface> interface; 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci if (backendContext.fVkExtensions) { 110cb93a386Sopenharmony_ci interface.reset(new GrVkInterface(backendContext.fGetProc, 111cb93a386Sopenharmony_ci backendContext.fInstance, 112cb93a386Sopenharmony_ci backendContext.fDevice, 113cb93a386Sopenharmony_ci instanceVersion, 114cb93a386Sopenharmony_ci physDevVersion, 115cb93a386Sopenharmony_ci backendContext.fVkExtensions)); 116cb93a386Sopenharmony_ci if (!interface->validate(instanceVersion, physDevVersion, backendContext.fVkExtensions)) { 117cb93a386Sopenharmony_ci return nullptr; 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci } else { 120cb93a386Sopenharmony_ci GrVkExtensions extensions; 121cb93a386Sopenharmony_ci // The only extension flag that may effect the vulkan backend is the swapchain extension. We 122cb93a386Sopenharmony_ci // need to know if this is enabled to know if we can transition to a present layout when 123cb93a386Sopenharmony_ci // flushing a surface. 124cb93a386Sopenharmony_ci if (backendContext.fExtensions & kKHR_swapchain_GrVkExtensionFlag) { 125cb93a386Sopenharmony_ci const char* swapChainExtName = VK_KHR_SWAPCHAIN_EXTENSION_NAME; 126cb93a386Sopenharmony_ci extensions.init(backendContext.fGetProc, backendContext.fInstance, 127cb93a386Sopenharmony_ci backendContext.fPhysicalDevice, 0, nullptr, 1, &swapChainExtName); 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci interface.reset(new GrVkInterface(backendContext.fGetProc, 130cb93a386Sopenharmony_ci backendContext.fInstance, 131cb93a386Sopenharmony_ci backendContext.fDevice, 132cb93a386Sopenharmony_ci instanceVersion, 133cb93a386Sopenharmony_ci physDevVersion, 134cb93a386Sopenharmony_ci &extensions)); 135cb93a386Sopenharmony_ci if (!interface->validate(instanceVersion, physDevVersion, &extensions)) { 136cb93a386Sopenharmony_ci return nullptr; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci sk_sp<GrVkCaps> caps; 141cb93a386Sopenharmony_ci if (backendContext.fDeviceFeatures2) { 142cb93a386Sopenharmony_ci caps.reset(new GrVkCaps(options, interface.get(), backendContext.fPhysicalDevice, 143cb93a386Sopenharmony_ci *backendContext.fDeviceFeatures2, instanceVersion, physDevVersion, 144cb93a386Sopenharmony_ci *backendContext.fVkExtensions, backendContext.fProtectedContext)); 145cb93a386Sopenharmony_ci } else if (backendContext.fDeviceFeatures) { 146cb93a386Sopenharmony_ci VkPhysicalDeviceFeatures2 features2; 147cb93a386Sopenharmony_ci features2.pNext = nullptr; 148cb93a386Sopenharmony_ci features2.features = *backendContext.fDeviceFeatures; 149cb93a386Sopenharmony_ci caps.reset(new GrVkCaps(options, interface.get(), backendContext.fPhysicalDevice, 150cb93a386Sopenharmony_ci features2, instanceVersion, physDevVersion, 151cb93a386Sopenharmony_ci *backendContext.fVkExtensions, backendContext.fProtectedContext)); 152cb93a386Sopenharmony_ci } else { 153cb93a386Sopenharmony_ci VkPhysicalDeviceFeatures2 features; 154cb93a386Sopenharmony_ci memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2)); 155cb93a386Sopenharmony_ci features.pNext = nullptr; 156cb93a386Sopenharmony_ci if (backendContext.fFeatures & kGeometryShader_GrVkFeatureFlag) { 157cb93a386Sopenharmony_ci features.features.geometryShader = true; 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci if (backendContext.fFeatures & kDualSrcBlend_GrVkFeatureFlag) { 160cb93a386Sopenharmony_ci features.features.dualSrcBlend = true; 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci if (backendContext.fFeatures & kSampleRateShading_GrVkFeatureFlag) { 163cb93a386Sopenharmony_ci features.features.sampleRateShading = true; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci GrVkExtensions extensions; 166cb93a386Sopenharmony_ci // The only extension flag that may effect the vulkan backend is the swapchain extension. We 167cb93a386Sopenharmony_ci // need to know if this is enabled to know if we can transition to a present layout when 168cb93a386Sopenharmony_ci // flushing a surface. 169cb93a386Sopenharmony_ci if (backendContext.fExtensions & kKHR_swapchain_GrVkExtensionFlag) { 170cb93a386Sopenharmony_ci const char* swapChainExtName = VK_KHR_SWAPCHAIN_EXTENSION_NAME; 171cb93a386Sopenharmony_ci extensions.init(backendContext.fGetProc, backendContext.fInstance, 172cb93a386Sopenharmony_ci backendContext.fPhysicalDevice, 0, nullptr, 1, &swapChainExtName); 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci caps.reset(new GrVkCaps(options, interface.get(), backendContext.fPhysicalDevice, 175cb93a386Sopenharmony_ci features, instanceVersion, physDevVersion, extensions, 176cb93a386Sopenharmony_ci backendContext.fProtectedContext)); 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci if (!caps) { 180cb93a386Sopenharmony_ci return nullptr; 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci sk_sp<GrVkMemoryAllocator> memoryAllocator = backendContext.fMemoryAllocator; 184cb93a386Sopenharmony_ci if (!memoryAllocator) { 185cb93a386Sopenharmony_ci // We were not given a memory allocator at creation 186cb93a386Sopenharmony_ci memoryAllocator = GrVkAMDMemoryAllocator::Make(backendContext.fInstance, 187cb93a386Sopenharmony_ci backendContext.fPhysicalDevice, 188cb93a386Sopenharmony_ci backendContext.fDevice, physDevVersion, 189cb93a386Sopenharmony_ci backendContext.fVkExtensions, interface, 190cb93a386Sopenharmony_ci caps.get()); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci if (!memoryAllocator) { 193cb93a386Sopenharmony_ci SkDEBUGFAIL("No supplied vulkan memory allocator and unable to create one internally."); 194cb93a386Sopenharmony_ci return nullptr; 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci const size_t maxBlockCount = SkGetVmaBlockCountMax(); // limit memory hols for vma cache 197cb93a386Sopenharmony_ci sk_sp<GrVkMemoryAllocator> memoryAllocatorCacheImage = 198cb93a386Sopenharmony_ci GrVkAMDMemoryAllocator::Make(backendContext.fInstance, 199cb93a386Sopenharmony_ci backendContext.fPhysicalDevice, 200cb93a386Sopenharmony_ci backendContext.fDevice, physDevVersion, 201cb93a386Sopenharmony_ci backendContext.fVkExtensions, interface, 202cb93a386Sopenharmony_ci caps.get(), true, maxBlockCount); 203cb93a386Sopenharmony_ci if (!memoryAllocatorCacheImage) { 204cb93a386Sopenharmony_ci SkDEBUGFAIL("No supplied vulkan memory allocator for cache image and unable to create one internally."); 205cb93a386Sopenharmony_ci return nullptr; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci sk_sp<GrVkGpu> vkGpu(new GrVkGpu(direct, backendContext, std::move(caps), interface, 209cb93a386Sopenharmony_ci instanceVersion, physDevVersion, 210cb93a386Sopenharmony_ci std::move(memoryAllocator), 211cb93a386Sopenharmony_ci std::move(memoryAllocatorCacheImage))); 212cb93a386Sopenharmony_ci if (backendContext.fProtectedContext == GrProtected::kYes && 213cb93a386Sopenharmony_ci !vkGpu->vkCaps().supportsProtectedMemory()) { 214cb93a386Sopenharmony_ci return nullptr; 215cb93a386Sopenharmony_ci } 216cb93a386Sopenharmony_ci return std::move(vkGpu); 217cb93a386Sopenharmony_ci} 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ciGrVkGpu::GrVkGpu(GrDirectContext* direct, const GrVkBackendContext& backendContext, 222cb93a386Sopenharmony_ci sk_sp<GrVkCaps> caps, sk_sp<const GrVkInterface> interface, 223cb93a386Sopenharmony_ci uint32_t instanceVersion, uint32_t physicalDeviceVersion, 224cb93a386Sopenharmony_ci sk_sp<GrVkMemoryAllocator> memoryAllocator, 225cb93a386Sopenharmony_ci sk_sp<GrVkMemoryAllocator> memoryAllocatorCacheImage) 226cb93a386Sopenharmony_ci : INHERITED(direct) 227cb93a386Sopenharmony_ci , fInterface(std::move(interface)) 228cb93a386Sopenharmony_ci , fMemoryAllocator(std::move(memoryAllocator)) 229cb93a386Sopenharmony_ci , fMemoryAllocatorCacheImage(std::move(memoryAllocatorCacheImage)) 230cb93a386Sopenharmony_ci , fVkCaps(std::move(caps)) 231cb93a386Sopenharmony_ci , fPhysicalDevice(backendContext.fPhysicalDevice) 232cb93a386Sopenharmony_ci , fDevice(backendContext.fDevice) 233cb93a386Sopenharmony_ci , fQueue(backendContext.fQueue) 234cb93a386Sopenharmony_ci , fQueueIndex(backendContext.fGraphicsQueueIndex) 235cb93a386Sopenharmony_ci , fResourceProvider(this) 236cb93a386Sopenharmony_ci , fStagingBufferManager(this) 237cb93a386Sopenharmony_ci , fDisconnected(false) 238cb93a386Sopenharmony_ci , fProtectedContext(backendContext.fProtectedContext) { 239cb93a386Sopenharmony_ci SkASSERT(!backendContext.fOwnsInstanceAndDevice); 240cb93a386Sopenharmony_ci SkASSERT(fMemoryAllocator); 241cb93a386Sopenharmony_ci SkASSERT(fMemoryAllocatorCacheImage); 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci this->initCapsAndCompiler(fVkCaps); 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci VK_CALL(GetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &fPhysDevProps)); 246cb93a386Sopenharmony_ci VK_CALL(GetPhysicalDeviceMemoryProperties(backendContext.fPhysicalDevice, &fPhysDevMemProps)); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci fResourceProvider.init(); 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci fMainCmdPool = fResourceProvider.findOrCreateCommandPool(); 251cb93a386Sopenharmony_ci if (fMainCmdPool) { 252cb93a386Sopenharmony_ci fMainCmdBuffer = fMainCmdPool->getPrimaryCommandBuffer(); 253cb93a386Sopenharmony_ci SkASSERT(this->currentCommandBuffer()); 254cb93a386Sopenharmony_ci this->currentCommandBuffer()->begin(this); 255cb93a386Sopenharmony_ci } 256cb93a386Sopenharmony_ci} 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_civoid GrVkGpu::destroyResources() { 259cb93a386Sopenharmony_ci if (fMainCmdPool) { 260cb93a386Sopenharmony_ci fMainCmdPool->getPrimaryCommandBuffer()->end(this, /*abandoningBuffer=*/true); 261cb93a386Sopenharmony_ci fMainCmdPool->close(); 262cb93a386Sopenharmony_ci } 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci // wait for all commands to finish 265cb93a386Sopenharmony_ci this->finishOutstandingGpuWork(); 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_ci if (fMainCmdPool) { 268cb93a386Sopenharmony_ci fMainCmdPool->unref(); 269cb93a386Sopenharmony_ci fMainCmdPool = nullptr; 270cb93a386Sopenharmony_ci } 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) { 273cb93a386Sopenharmony_ci fSemaphoresToWaitOn[i]->unref(); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci fSemaphoresToWaitOn.reset(); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci for (int i = 0; i < fSemaphoresToSignal.count(); ++i) { 278cb93a386Sopenharmony_ci fSemaphoresToSignal[i]->unref(); 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci fSemaphoresToSignal.reset(); 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ci fStagingBufferManager.reset(); 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci fMSAALoadManager.destroyResources(this); 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_ci // must call this just before we destroy the command pool and VkDevice 287cb93a386Sopenharmony_ci fResourceProvider.destroyResources(); 288cb93a386Sopenharmony_ci} 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ciGrVkGpu::~GrVkGpu() { 291cb93a386Sopenharmony_ci if (!fDisconnected) { 292cb93a386Sopenharmony_ci this->destroyResources(); 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci // We don't delete the memory allocator until the very end of the GrVkGpu lifetime so that 295cb93a386Sopenharmony_ci // clients can continue to delete backend textures even after a context has been abandoned. 296cb93a386Sopenharmony_ci fMemoryAllocator.reset(); 297cb93a386Sopenharmony_ci fMemoryAllocatorCacheImage.reset(); 298cb93a386Sopenharmony_ci} 299cb93a386Sopenharmony_ci 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_civoid GrVkGpu::disconnect(DisconnectType type) { 302cb93a386Sopenharmony_ci INHERITED::disconnect(type); 303cb93a386Sopenharmony_ci if (!fDisconnected) { 304cb93a386Sopenharmony_ci this->destroyResources(); 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci fSemaphoresToWaitOn.reset(); 307cb93a386Sopenharmony_ci fSemaphoresToSignal.reset(); 308cb93a386Sopenharmony_ci fMainCmdBuffer = nullptr; 309cb93a386Sopenharmony_ci fDisconnected = true; 310cb93a386Sopenharmony_ci } 311cb93a386Sopenharmony_ci} 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_ciGrThreadSafePipelineBuilder* GrVkGpu::pipelineBuilder() { 314cb93a386Sopenharmony_ci return fResourceProvider.pipelineStateCache(); 315cb93a386Sopenharmony_ci} 316cb93a386Sopenharmony_ci 317cb93a386Sopenharmony_cisk_sp<GrThreadSafePipelineBuilder> GrVkGpu::refPipelineBuilder() { 318cb93a386Sopenharmony_ci return fResourceProvider.refPipelineStateCache(); 319cb93a386Sopenharmony_ci} 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ciGrOpsRenderPass* GrVkGpu::onGetOpsRenderPass( 324cb93a386Sopenharmony_ci GrRenderTarget* rt, 325cb93a386Sopenharmony_ci bool useMSAASurface, 326cb93a386Sopenharmony_ci GrAttachment* stencil, 327cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 328cb93a386Sopenharmony_ci const SkIRect& bounds, 329cb93a386Sopenharmony_ci const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, 330cb93a386Sopenharmony_ci const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, 331cb93a386Sopenharmony_ci const SkTArray<GrSurfaceProxy*, true>& sampledProxies, 332cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers) { 333cb93a386Sopenharmony_ci if (!fCachedOpsRenderPass) { 334cb93a386Sopenharmony_ci fCachedOpsRenderPass = std::make_unique<GrVkOpsRenderPass>(this); 335cb93a386Sopenharmony_ci } 336cb93a386Sopenharmony_ci 337cb93a386Sopenharmony_ci // For the given render target and requested render pass features we need to find a compatible 338cb93a386Sopenharmony_ci // framebuffer to use for the render pass. Technically it is the underlying VkRenderPass that 339cb93a386Sopenharmony_ci // is compatible, but that is part of the framebuffer that we get here. 340cb93a386Sopenharmony_ci GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ci SkASSERT(!useMSAASurface || 343cb93a386Sopenharmony_ci rt->numSamples() > 1 || 344cb93a386Sopenharmony_ci (this->vkCaps().supportsDiscardableMSAAForDMSAA() && 345cb93a386Sopenharmony_ci vkRT->resolveAttachment() && 346cb93a386Sopenharmony_ci vkRT->resolveAttachment()->supportsInputAttachmentUsage())); 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_ci // Covert the GrXferBarrierFlags into render pass self dependency flags 349cb93a386Sopenharmony_ci GrVkRenderPass::SelfDependencyFlags selfDepFlags = GrVkRenderPass::SelfDependencyFlags::kNone; 350cb93a386Sopenharmony_ci if (renderPassXferBarriers & GrXferBarrierFlags::kBlend) { 351cb93a386Sopenharmony_ci selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend; 352cb93a386Sopenharmony_ci } 353cb93a386Sopenharmony_ci if (renderPassXferBarriers & GrXferBarrierFlags::kTexture) { 354cb93a386Sopenharmony_ci selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForInputAttachment; 355cb93a386Sopenharmony_ci } 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci // Figure out if we need a resolve attachment for this render pass. A resolve attachment is 358cb93a386Sopenharmony_ci // needed if we are using msaa to draw with a discardable msaa attachment. If we are in this 359cb93a386Sopenharmony_ci // case we also need to update the color load/store ops since we don't want to ever load or 360cb93a386Sopenharmony_ci // store the msaa color attachment, but may need to for the resolve attachment. 361cb93a386Sopenharmony_ci GrOpsRenderPass::LoadAndStoreInfo localColorInfo = colorInfo; 362cb93a386Sopenharmony_ci bool withResolve = false; 363cb93a386Sopenharmony_ci GrVkRenderPass::LoadFromResolve loadFromResolve = GrVkRenderPass::LoadFromResolve::kNo; 364cb93a386Sopenharmony_ci GrOpsRenderPass::LoadAndStoreInfo resolveInfo{GrLoadOp::kLoad, GrStoreOp::kStore, {}}; 365cb93a386Sopenharmony_ci if (useMSAASurface && this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) { 366cb93a386Sopenharmony_ci withResolve = true; 367cb93a386Sopenharmony_ci localColorInfo.fStoreOp = GrStoreOp::kDiscard; 368cb93a386Sopenharmony_ci if (colorInfo.fLoadOp == GrLoadOp::kLoad) { 369cb93a386Sopenharmony_ci loadFromResolve = GrVkRenderPass::LoadFromResolve::kLoad; 370cb93a386Sopenharmony_ci localColorInfo.fLoadOp = GrLoadOp::kDiscard; 371cb93a386Sopenharmony_ci } else { 372cb93a386Sopenharmony_ci resolveInfo.fLoadOp = GrLoadOp::kDiscard; 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci } 375cb93a386Sopenharmony_ci 376cb93a386Sopenharmony_ci // Get the framebuffer to use for the render pass 377cb93a386Sopenharmony_ci sk_sp<GrVkFramebuffer> framebuffer; 378cb93a386Sopenharmony_ci if (vkRT->wrapsSecondaryCommandBuffer()) { 379cb93a386Sopenharmony_ci framebuffer = vkRT->externalFramebuffer(); 380cb93a386Sopenharmony_ci } else { 381cb93a386Sopenharmony_ci auto fb = vkRT->getFramebuffer(withResolve, SkToBool(stencil), selfDepFlags, 382cb93a386Sopenharmony_ci loadFromResolve); 383cb93a386Sopenharmony_ci framebuffer = sk_ref_sp(fb); 384cb93a386Sopenharmony_ci } 385cb93a386Sopenharmony_ci if (!framebuffer) { 386cb93a386Sopenharmony_ci return nullptr; 387cb93a386Sopenharmony_ci } 388cb93a386Sopenharmony_ci 389cb93a386Sopenharmony_ci if (!fCachedOpsRenderPass->set(rt, std::move(framebuffer), origin, bounds, localColorInfo, 390cb93a386Sopenharmony_ci stencilInfo, resolveInfo, selfDepFlags, loadFromResolve, 391cb93a386Sopenharmony_ci sampledProxies)) { 392cb93a386Sopenharmony_ci return nullptr; 393cb93a386Sopenharmony_ci } 394cb93a386Sopenharmony_ci return fCachedOpsRenderPass.get(); 395cb93a386Sopenharmony_ci} 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_cibool GrVkGpu::submitCommandBuffer(SyncQueue sync) { 398cb93a386Sopenharmony_ci TRACE_EVENT0("skia.gpu", TRACE_FUNC); 399cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 400cb93a386Sopenharmony_ci return false; 401cb93a386Sopenharmony_ci } 402cb93a386Sopenharmony_ci SkASSERT(!fCachedOpsRenderPass || !fCachedOpsRenderPass->isActive()); 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()->hasWork() && kForce_SyncQueue != sync && 405cb93a386Sopenharmony_ci !fSemaphoresToSignal.count() && !fSemaphoresToWaitOn.count()) { 406cb93a386Sopenharmony_ci // We may have added finished procs during the flush call. Since there is no actual work 407cb93a386Sopenharmony_ci // we are not submitting the command buffer and may never come back around to submit it. 408cb93a386Sopenharmony_ci // Thus we call all current finished procs manually, since the work has technically 409cb93a386Sopenharmony_ci // finished. 410cb93a386Sopenharmony_ci this->currentCommandBuffer()->callFinishedProcs(); 411cb93a386Sopenharmony_ci SkASSERT(fDrawables.empty()); 412cb93a386Sopenharmony_ci fResourceProvider.checkCommandBuffers(); 413cb93a386Sopenharmony_ci return true; 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci 416cb93a386Sopenharmony_ci fMainCmdBuffer->end(this); 417cb93a386Sopenharmony_ci SkASSERT(fMainCmdPool); 418cb93a386Sopenharmony_ci fMainCmdPool->close(); 419cb93a386Sopenharmony_ci bool didSubmit = fMainCmdBuffer->submitToQueue(this, fQueue, fSemaphoresToSignal, 420cb93a386Sopenharmony_ci fSemaphoresToWaitOn); 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci if (didSubmit && sync == kForce_SyncQueue) { 423cb93a386Sopenharmony_ci fMainCmdBuffer->forceSync(this); 424cb93a386Sopenharmony_ci } 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_ci // We must delete any drawables that had to wait until submit to destroy. 427cb93a386Sopenharmony_ci fDrawables.reset(); 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ci // If we didn't submit the command buffer then we did not wait on any semaphores. We will 430cb93a386Sopenharmony_ci // continue to hold onto these semaphores and wait on them during the next command buffer 431cb93a386Sopenharmony_ci // submission. 432cb93a386Sopenharmony_ci if (didSubmit) { 433cb93a386Sopenharmony_ci for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) { 434cb93a386Sopenharmony_ci fSemaphoresToWaitOn[i]->unref(); 435cb93a386Sopenharmony_ci } 436cb93a386Sopenharmony_ci fSemaphoresToWaitOn.reset(); 437cb93a386Sopenharmony_ci } 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_ci // Even if we did not submit the command buffer, we drop all the signal semaphores since we will 440cb93a386Sopenharmony_ci // not try to recover the work that wasn't submitted and instead just drop it all. The client 441cb93a386Sopenharmony_ci // will be notified that the semaphores were not submit so that they will not try to wait on 442cb93a386Sopenharmony_ci // them. 443cb93a386Sopenharmony_ci for (int i = 0; i < fSemaphoresToSignal.count(); ++i) { 444cb93a386Sopenharmony_ci fSemaphoresToSignal[i]->unref(); 445cb93a386Sopenharmony_ci } 446cb93a386Sopenharmony_ci fSemaphoresToSignal.reset(); 447cb93a386Sopenharmony_ci 448cb93a386Sopenharmony_ci // Release old command pool and create a new one 449cb93a386Sopenharmony_ci fMainCmdPool->unref(); 450cb93a386Sopenharmony_ci fMainCmdPool = fResourceProvider.findOrCreateCommandPool(); 451cb93a386Sopenharmony_ci if (fMainCmdPool) { 452cb93a386Sopenharmony_ci fMainCmdBuffer = fMainCmdPool->getPrimaryCommandBuffer(); 453cb93a386Sopenharmony_ci SkASSERT(fMainCmdBuffer); 454cb93a386Sopenharmony_ci fMainCmdBuffer->begin(this); 455cb93a386Sopenharmony_ci } else { 456cb93a386Sopenharmony_ci fMainCmdBuffer = nullptr; 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci // We must wait to call checkCommandBuffers until after we get a new command buffer. The 459cb93a386Sopenharmony_ci // checkCommandBuffers may trigger a releaseProc which may cause us to insert a barrier for a 460cb93a386Sopenharmony_ci // released GrVkImage. That barrier needs to be put into a new command buffer and not the old 461cb93a386Sopenharmony_ci // one that was just submitted. 462cb93a386Sopenharmony_ci fResourceProvider.checkCommandBuffers(); 463cb93a386Sopenharmony_ci return didSubmit; 464cb93a386Sopenharmony_ci} 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 467cb93a386Sopenharmony_cisk_sp<GrGpuBuffer> GrVkGpu::onCreateBuffer(size_t size, GrGpuBufferType type, 468cb93a386Sopenharmony_ci GrAccessPattern accessPattern, const void* data) { 469cb93a386Sopenharmony_ci#ifdef SK_DEBUG 470cb93a386Sopenharmony_ci switch (type) { 471cb93a386Sopenharmony_ci case GrGpuBufferType::kVertex: 472cb93a386Sopenharmony_ci case GrGpuBufferType::kIndex: 473cb93a386Sopenharmony_ci case GrGpuBufferType::kDrawIndirect: 474cb93a386Sopenharmony_ci SkASSERT(accessPattern == kDynamic_GrAccessPattern || 475cb93a386Sopenharmony_ci accessPattern == kStatic_GrAccessPattern); 476cb93a386Sopenharmony_ci break; 477cb93a386Sopenharmony_ci case GrGpuBufferType::kXferCpuToGpu: 478cb93a386Sopenharmony_ci SkASSERT(accessPattern == kDynamic_GrAccessPattern); 479cb93a386Sopenharmony_ci break; 480cb93a386Sopenharmony_ci case GrGpuBufferType::kXferGpuToCpu: 481cb93a386Sopenharmony_ci SkASSERT(accessPattern == kDynamic_GrAccessPattern || 482cb93a386Sopenharmony_ci accessPattern == kStream_GrAccessPattern); 483cb93a386Sopenharmony_ci break; 484cb93a386Sopenharmony_ci case GrGpuBufferType::kUniform: 485cb93a386Sopenharmony_ci SkASSERT(accessPattern == kDynamic_GrAccessPattern); 486cb93a386Sopenharmony_ci break; 487cb93a386Sopenharmony_ci } 488cb93a386Sopenharmony_ci#endif 489cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> buff = GrVkBuffer::Make(this, size, type, accessPattern); 490cb93a386Sopenharmony_ci 491cb93a386Sopenharmony_ci if (data && buff) { 492cb93a386Sopenharmony_ci buff->updateData(data, size); 493cb93a386Sopenharmony_ci } 494cb93a386Sopenharmony_ci return buff; 495cb93a386Sopenharmony_ci} 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_cibool GrVkGpu::onWritePixels(GrSurface* surface, 498cb93a386Sopenharmony_ci SkIRect rect, 499cb93a386Sopenharmony_ci GrColorType surfaceColorType, 500cb93a386Sopenharmony_ci GrColorType srcColorType, 501cb93a386Sopenharmony_ci const GrMipLevel texels[], 502cb93a386Sopenharmony_ci int mipLevelCount, 503cb93a386Sopenharmony_ci bool prepForTexSampling) { 504cb93a386Sopenharmony_ci GrVkTexture* texture = static_cast<GrVkTexture*>(surface->asTexture()); 505cb93a386Sopenharmony_ci if (!texture) { 506cb93a386Sopenharmony_ci return false; 507cb93a386Sopenharmony_ci } 508cb93a386Sopenharmony_ci GrVkImage* texImage = texture->textureImage(); 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci // Make sure we have at least the base level 511cb93a386Sopenharmony_ci if (!mipLevelCount || !texels[0].fPixels) { 512cb93a386Sopenharmony_ci return false; 513cb93a386Sopenharmony_ci } 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci SkASSERT(!GrVkFormatIsCompressed(texImage->imageFormat())); 516cb93a386Sopenharmony_ci bool success = false; 517cb93a386Sopenharmony_ci bool linearTiling = texImage->isLinearTiled(); 518cb93a386Sopenharmony_ci if (linearTiling) { 519cb93a386Sopenharmony_ci if (mipLevelCount > 1) { 520cb93a386Sopenharmony_ci SkDebugf("Can't upload mipmap data to linear tiled texture"); 521cb93a386Sopenharmony_ci return false; 522cb93a386Sopenharmony_ci } 523cb93a386Sopenharmony_ci if (VK_IMAGE_LAYOUT_PREINITIALIZED != texImage->currentLayout()) { 524cb93a386Sopenharmony_ci // Need to change the layout to general in order to perform a host write 525cb93a386Sopenharmony_ci texImage->setImageLayout(this, 526cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 527cb93a386Sopenharmony_ci VK_ACCESS_HOST_WRITE_BIT, 528cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_HOST_BIT, 529cb93a386Sopenharmony_ci false); 530cb93a386Sopenharmony_ci if (!this->submitCommandBuffer(kForce_SyncQueue)) { 531cb93a386Sopenharmony_ci return false; 532cb93a386Sopenharmony_ci } 533cb93a386Sopenharmony_ci } 534cb93a386Sopenharmony_ci success = this->uploadTexDataLinear(texImage, 535cb93a386Sopenharmony_ci rect, 536cb93a386Sopenharmony_ci srcColorType, 537cb93a386Sopenharmony_ci texels[0].fPixels, 538cb93a386Sopenharmony_ci texels[0].fRowBytes); 539cb93a386Sopenharmony_ci } else { 540cb93a386Sopenharmony_ci SkASSERT(mipLevelCount <= (int)texImage->mipLevels()); 541cb93a386Sopenharmony_ci success = this->uploadTexDataOptimal(texImage, 542cb93a386Sopenharmony_ci rect, 543cb93a386Sopenharmony_ci srcColorType, 544cb93a386Sopenharmony_ci texels, 545cb93a386Sopenharmony_ci mipLevelCount); 546cb93a386Sopenharmony_ci if (1 == mipLevelCount) { 547cb93a386Sopenharmony_ci texture->markMipmapsDirty(); 548cb93a386Sopenharmony_ci } 549cb93a386Sopenharmony_ci } 550cb93a386Sopenharmony_ci 551cb93a386Sopenharmony_ci if (prepForTexSampling) { 552cb93a386Sopenharmony_ci texImage->setImageLayout(this, 553cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 554cb93a386Sopenharmony_ci VK_ACCESS_SHADER_READ_BIT, 555cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 556cb93a386Sopenharmony_ci false); 557cb93a386Sopenharmony_ci } 558cb93a386Sopenharmony_ci 559cb93a386Sopenharmony_ci return success; 560cb93a386Sopenharmony_ci} 561cb93a386Sopenharmony_ci 562cb93a386Sopenharmony_cibool GrVkGpu::onTransferPixelsTo(GrTexture* texture, 563cb93a386Sopenharmony_ci SkIRect rect, 564cb93a386Sopenharmony_ci GrColorType surfaceColorType, 565cb93a386Sopenharmony_ci GrColorType bufferColorType, 566cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> transferBuffer, 567cb93a386Sopenharmony_ci size_t bufferOffset, 568cb93a386Sopenharmony_ci size_t rowBytes) { 569cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 570cb93a386Sopenharmony_ci return false; 571cb93a386Sopenharmony_ci } 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_ci size_t bpp = GrColorTypeBytesPerPixel(bufferColorType); 574cb93a386Sopenharmony_ci if (GrBackendFormatBytesPerPixel(texture->backendFormat()) != bpp) { 575cb93a386Sopenharmony_ci return false; 576cb93a386Sopenharmony_ci } 577cb93a386Sopenharmony_ci 578cb93a386Sopenharmony_ci // Vulkan only supports offsets that are both 4-byte aligned and aligned to a pixel. 579cb93a386Sopenharmony_ci if ((bufferOffset & 0x3) || (bufferOffset % bpp)) { 580cb93a386Sopenharmony_ci return false; 581cb93a386Sopenharmony_ci } 582cb93a386Sopenharmony_ci GrVkTexture* tex = static_cast<GrVkTexture*>(texture); 583cb93a386Sopenharmony_ci if (!tex) { 584cb93a386Sopenharmony_ci return false; 585cb93a386Sopenharmony_ci } 586cb93a386Sopenharmony_ci GrVkImage* vkImage = tex->textureImage(); 587cb93a386Sopenharmony_ci VkFormat format = vkImage->imageFormat(); 588cb93a386Sopenharmony_ci 589cb93a386Sopenharmony_ci // Can't transfer compressed data 590cb93a386Sopenharmony_ci SkASSERT(!GrVkFormatIsCompressed(format)); 591cb93a386Sopenharmony_ci 592cb93a386Sopenharmony_ci if (!transferBuffer) { 593cb93a386Sopenharmony_ci return false; 594cb93a386Sopenharmony_ci } 595cb93a386Sopenharmony_ci 596cb93a386Sopenharmony_ci if (bufferColorType != this->vkCaps().transferColorType(format, surfaceColorType)) { 597cb93a386Sopenharmony_ci return false; 598cb93a386Sopenharmony_ci } 599cb93a386Sopenharmony_ci SkASSERT(GrVkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType)); 600cb93a386Sopenharmony_ci 601cb93a386Sopenharmony_ci SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect)); 602cb93a386Sopenharmony_ci 603cb93a386Sopenharmony_ci // Set up copy region 604cb93a386Sopenharmony_ci VkBufferImageCopy region; 605cb93a386Sopenharmony_ci memset(®ion, 0, sizeof(VkBufferImageCopy)); 606cb93a386Sopenharmony_ci region.bufferOffset = bufferOffset; 607cb93a386Sopenharmony_ci region.bufferRowLength = (uint32_t)(rowBytes/bpp); 608cb93a386Sopenharmony_ci region.bufferImageHeight = 0; 609cb93a386Sopenharmony_ci region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 610cb93a386Sopenharmony_ci region.imageOffset = { rect.left(), rect.top(), 0 }; 611cb93a386Sopenharmony_ci region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 }; 612cb93a386Sopenharmony_ci 613cb93a386Sopenharmony_ci // Change layout of our target so it can be copied to 614cb93a386Sopenharmony_ci vkImage->setImageLayout(this, 615cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 616cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 617cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 618cb93a386Sopenharmony_ci false); 619cb93a386Sopenharmony_ci 620cb93a386Sopenharmony_ci const GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get()); 621cb93a386Sopenharmony_ci 622cb93a386Sopenharmony_ci // Copy the buffer to the image. 623cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyBufferToImage(this, 624cb93a386Sopenharmony_ci vkBuffer->vkBuffer(), 625cb93a386Sopenharmony_ci vkImage, 626cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 627cb93a386Sopenharmony_ci 1, 628cb93a386Sopenharmony_ci ®ion); 629cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrBuffer(std::move(transferBuffer)); 630cb93a386Sopenharmony_ci 631cb93a386Sopenharmony_ci tex->markMipmapsDirty(); 632cb93a386Sopenharmony_ci return true; 633cb93a386Sopenharmony_ci} 634cb93a386Sopenharmony_ci 635cb93a386Sopenharmony_cibool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, 636cb93a386Sopenharmony_ci SkIRect rect, 637cb93a386Sopenharmony_ci GrColorType surfaceColorType, 638cb93a386Sopenharmony_ci GrColorType bufferColorType, 639cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> transferBuffer, 640cb93a386Sopenharmony_ci size_t offset) { 641cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 642cb93a386Sopenharmony_ci return false; 643cb93a386Sopenharmony_ci } 644cb93a386Sopenharmony_ci SkASSERT(surface); 645cb93a386Sopenharmony_ci SkASSERT(transferBuffer); 646cb93a386Sopenharmony_ci if (fProtectedContext == GrProtected::kYes) { 647cb93a386Sopenharmony_ci return false; 648cb93a386Sopenharmony_ci } 649cb93a386Sopenharmony_ci 650cb93a386Sopenharmony_ci GrVkImage* srcImage; 651cb93a386Sopenharmony_ci if (GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget())) { 652cb93a386Sopenharmony_ci // Reading from render targets that wrap a secondary command buffer is not allowed since 653cb93a386Sopenharmony_ci // it would require us to know the VkImage, which we don't have, as well as need us to 654cb93a386Sopenharmony_ci // stop and start the VkRenderPass which we don't have access to. 655cb93a386Sopenharmony_ci if (rt->wrapsSecondaryCommandBuffer()) { 656cb93a386Sopenharmony_ci return false; 657cb93a386Sopenharmony_ci } 658cb93a386Sopenharmony_ci if (!rt->nonMSAAAttachment()) { 659cb93a386Sopenharmony_ci return false; 660cb93a386Sopenharmony_ci } 661cb93a386Sopenharmony_ci srcImage = rt->nonMSAAAttachment(); 662cb93a386Sopenharmony_ci } else { 663cb93a386Sopenharmony_ci SkASSERT(surface->asTexture()); 664cb93a386Sopenharmony_ci srcImage = static_cast<GrVkTexture*>(surface->asTexture())->textureImage(); 665cb93a386Sopenharmony_ci } 666cb93a386Sopenharmony_ci 667cb93a386Sopenharmony_ci VkFormat format = srcImage->imageFormat(); 668cb93a386Sopenharmony_ci if (bufferColorType != this->vkCaps().transferColorType(format, surfaceColorType)) { 669cb93a386Sopenharmony_ci return false; 670cb93a386Sopenharmony_ci } 671cb93a386Sopenharmony_ci SkASSERT(GrVkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType)); 672cb93a386Sopenharmony_ci 673cb93a386Sopenharmony_ci // Set up copy region 674cb93a386Sopenharmony_ci VkBufferImageCopy region; 675cb93a386Sopenharmony_ci memset(®ion, 0, sizeof(VkBufferImageCopy)); 676cb93a386Sopenharmony_ci region.bufferOffset = offset; 677cb93a386Sopenharmony_ci region.bufferRowLength = rect.width(); 678cb93a386Sopenharmony_ci region.bufferImageHeight = 0; 679cb93a386Sopenharmony_ci region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 680cb93a386Sopenharmony_ci region.imageOffset = {rect.left(), rect.top(), 0}; 681cb93a386Sopenharmony_ci region.imageExtent = {(uint32_t)rect.width(), (uint32_t)rect.height(), 1}; 682cb93a386Sopenharmony_ci 683cb93a386Sopenharmony_ci srcImage->setImageLayout(this, 684cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 685cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, 686cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 687cb93a386Sopenharmony_ci false); 688cb93a386Sopenharmony_ci 689cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyImageToBuffer(this, srcImage, 690cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 691cb93a386Sopenharmony_ci transferBuffer, 1, ®ion); 692cb93a386Sopenharmony_ci 693cb93a386Sopenharmony_ci GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get()); 694cb93a386Sopenharmony_ci // Make sure the copy to buffer has finished. 695cb93a386Sopenharmony_ci vkBuffer->addMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, 696cb93a386Sopenharmony_ci VK_ACCESS_HOST_READ_BIT, 697cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 698cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_HOST_BIT, 699cb93a386Sopenharmony_ci false); 700cb93a386Sopenharmony_ci return true; 701cb93a386Sopenharmony_ci} 702cb93a386Sopenharmony_ci 703cb93a386Sopenharmony_civoid GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect, 704cb93a386Sopenharmony_ci const SkIPoint& dstPoint) { 705cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 706cb93a386Sopenharmony_ci return; 707cb93a386Sopenharmony_ci } 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci SkASSERT(dst); 710cb93a386Sopenharmony_ci SkASSERT(src && src->colorAttachment() && src->colorAttachment()->numSamples() > 1); 711cb93a386Sopenharmony_ci 712cb93a386Sopenharmony_ci VkImageResolve resolveInfo; 713cb93a386Sopenharmony_ci resolveInfo.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; 714cb93a386Sopenharmony_ci resolveInfo.srcOffset = {srcRect.fLeft, srcRect.fTop, 0}; 715cb93a386Sopenharmony_ci resolveInfo.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; 716cb93a386Sopenharmony_ci resolveInfo.dstOffset = {dstPoint.fX, dstPoint.fY, 0}; 717cb93a386Sopenharmony_ci resolveInfo.extent = {(uint32_t)srcRect.width(), (uint32_t)srcRect.height(), 1}; 718cb93a386Sopenharmony_ci 719cb93a386Sopenharmony_ci GrVkImage* dstImage; 720cb93a386Sopenharmony_ci GrRenderTarget* dstRT = dst->asRenderTarget(); 721cb93a386Sopenharmony_ci GrTexture* dstTex = dst->asTexture(); 722cb93a386Sopenharmony_ci if (dstTex) { 723cb93a386Sopenharmony_ci dstImage = static_cast<GrVkTexture*>(dstTex)->textureImage(); 724cb93a386Sopenharmony_ci } else { 725cb93a386Sopenharmony_ci SkASSERT(dst->asRenderTarget()); 726cb93a386Sopenharmony_ci dstImage = static_cast<GrVkRenderTarget*>(dstRT)->nonMSAAAttachment(); 727cb93a386Sopenharmony_ci } 728cb93a386Sopenharmony_ci SkASSERT(dstImage); 729cb93a386Sopenharmony_ci 730cb93a386Sopenharmony_ci dstImage->setImageLayout(this, 731cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 732cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 733cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 734cb93a386Sopenharmony_ci false); 735cb93a386Sopenharmony_ci 736cb93a386Sopenharmony_ci src->colorAttachment()->setImageLayout(this, 737cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 738cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, 739cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 740cb93a386Sopenharmony_ci false); 741cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src->colorAttachment())); 742cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst)); 743cb93a386Sopenharmony_ci this->currentCommandBuffer()->resolveImage(this, *src->colorAttachment(), *dstImage, 1, 744cb93a386Sopenharmony_ci &resolveInfo); 745cb93a386Sopenharmony_ci} 746cb93a386Sopenharmony_ci 747cb93a386Sopenharmony_civoid GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) { 748cb93a386Sopenharmony_ci SkASSERT(target->numSamples() > 1); 749cb93a386Sopenharmony_ci GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target); 750cb93a386Sopenharmony_ci SkASSERT(rt->colorAttachmentView() && rt->resolveAttachmentView()); 751cb93a386Sopenharmony_ci 752cb93a386Sopenharmony_ci if (this->vkCaps().renderTargetSupportsDiscardableMSAA(rt)) { 753cb93a386Sopenharmony_ci // We would have resolved the RT during the render pass; 754cb93a386Sopenharmony_ci return; 755cb93a386Sopenharmony_ci } 756cb93a386Sopenharmony_ci 757cb93a386Sopenharmony_ci this->resolveImage(target, rt, resolveRect, 758cb93a386Sopenharmony_ci SkIPoint::Make(resolveRect.x(), resolveRect.y())); 759cb93a386Sopenharmony_ci} 760cb93a386Sopenharmony_ci 761cb93a386Sopenharmony_cibool GrVkGpu::uploadTexDataLinear(GrVkImage* texImage, 762cb93a386Sopenharmony_ci SkIRect rect, 763cb93a386Sopenharmony_ci GrColorType dataColorType, 764cb93a386Sopenharmony_ci const void* data, 765cb93a386Sopenharmony_ci size_t rowBytes) { 766cb93a386Sopenharmony_ci SkASSERT(data); 767cb93a386Sopenharmony_ci SkASSERT(texImage->isLinearTiled()); 768cb93a386Sopenharmony_ci 769cb93a386Sopenharmony_ci SkASSERT(SkIRect::MakeSize(texImage->dimensions()).contains(rect)); 770cb93a386Sopenharmony_ci 771cb93a386Sopenharmony_ci size_t bpp = GrColorTypeBytesPerPixel(dataColorType); 772cb93a386Sopenharmony_ci size_t trimRowBytes = rect.width() * bpp; 773cb93a386Sopenharmony_ci 774cb93a386Sopenharmony_ci SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == texImage->currentLayout() || 775cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL == texImage->currentLayout()); 776cb93a386Sopenharmony_ci const VkImageSubresource subres = { 777cb93a386Sopenharmony_ci VK_IMAGE_ASPECT_COLOR_BIT, 778cb93a386Sopenharmony_ci 0, // mipLevel 779cb93a386Sopenharmony_ci 0, // arraySlice 780cb93a386Sopenharmony_ci }; 781cb93a386Sopenharmony_ci VkSubresourceLayout layout; 782cb93a386Sopenharmony_ci 783cb93a386Sopenharmony_ci const GrVkInterface* interface = this->vkInterface(); 784cb93a386Sopenharmony_ci 785cb93a386Sopenharmony_ci GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice, 786cb93a386Sopenharmony_ci texImage->image(), 787cb93a386Sopenharmony_ci &subres, 788cb93a386Sopenharmony_ci &layout)); 789cb93a386Sopenharmony_ci 790cb93a386Sopenharmony_ci const GrVkAlloc& alloc = texImage->alloc(); 791cb93a386Sopenharmony_ci if (VK_NULL_HANDLE == alloc.fMemory) { 792cb93a386Sopenharmony_ci return false; 793cb93a386Sopenharmony_ci } 794cb93a386Sopenharmony_ci VkDeviceSize offset = rect.top()*layout.rowPitch + rect.left()*bpp; 795cb93a386Sopenharmony_ci VkDeviceSize size = rect.height()*layout.rowPitch; 796cb93a386Sopenharmony_ci SkASSERT(size + offset <= alloc.fSize); 797cb93a386Sopenharmony_ci void* mapPtr = GrVkMemory::MapAlloc(this, alloc); 798cb93a386Sopenharmony_ci if (!mapPtr) { 799cb93a386Sopenharmony_ci return false; 800cb93a386Sopenharmony_ci } 801cb93a386Sopenharmony_ci mapPtr = reinterpret_cast<char*>(mapPtr) + offset; 802cb93a386Sopenharmony_ci 803cb93a386Sopenharmony_ci SkRectMemcpy(mapPtr, 804cb93a386Sopenharmony_ci static_cast<size_t>(layout.rowPitch), 805cb93a386Sopenharmony_ci data, 806cb93a386Sopenharmony_ci rowBytes, 807cb93a386Sopenharmony_ci trimRowBytes, 808cb93a386Sopenharmony_ci rect.height()); 809cb93a386Sopenharmony_ci 810cb93a386Sopenharmony_ci GrVkMemory::FlushMappedAlloc(this, alloc, offset, size); 811cb93a386Sopenharmony_ci GrVkMemory::UnmapAlloc(this, alloc); 812cb93a386Sopenharmony_ci 813cb93a386Sopenharmony_ci return true; 814cb93a386Sopenharmony_ci} 815cb93a386Sopenharmony_ci 816cb93a386Sopenharmony_ci// This fills in the 'regions' vector in preparation for copying a buffer to an image. 817cb93a386Sopenharmony_ci// 'individualMipOffsets' is filled in as a side-effect. 818cb93a386Sopenharmony_cistatic size_t fill_in_compressed_regions(GrStagingBufferManager* stagingBufferManager, 819cb93a386Sopenharmony_ci SkTArray<VkBufferImageCopy>* regions, 820cb93a386Sopenharmony_ci SkTArray<size_t>* individualMipOffsets, 821cb93a386Sopenharmony_ci GrStagingBufferManager::Slice* slice, 822cb93a386Sopenharmony_ci SkImage::CompressionType compression, 823cb93a386Sopenharmony_ci VkFormat vkFormat, 824cb93a386Sopenharmony_ci SkISize dimensions, 825cb93a386Sopenharmony_ci GrMipmapped mipmapped) { 826cb93a386Sopenharmony_ci SkASSERT(compression != SkImage::CompressionType::kNone); 827cb93a386Sopenharmony_ci int numMipLevels = 1; 828cb93a386Sopenharmony_ci if (mipmapped == GrMipmapped::kYes) { 829cb93a386Sopenharmony_ci numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; 830cb93a386Sopenharmony_ci } 831cb93a386Sopenharmony_ci 832cb93a386Sopenharmony_ci regions->reserve_back(numMipLevels); 833cb93a386Sopenharmony_ci individualMipOffsets->reserve_back(numMipLevels); 834cb93a386Sopenharmony_ci 835cb93a386Sopenharmony_ci size_t bytesPerBlock = GrVkFormatBytesPerBlock(vkFormat); 836cb93a386Sopenharmony_ci 837cb93a386Sopenharmony_ci size_t bufferSize = SkCompressedDataSize(compression, 838cb93a386Sopenharmony_ci dimensions, 839cb93a386Sopenharmony_ci individualMipOffsets, 840cb93a386Sopenharmony_ci mipmapped == GrMipmapped::kYes); 841cb93a386Sopenharmony_ci SkASSERT(individualMipOffsets->count() == numMipLevels); 842cb93a386Sopenharmony_ci 843cb93a386Sopenharmony_ci // Get a staging buffer slice to hold our mip data. 844cb93a386Sopenharmony_ci // Vulkan requires offsets in the buffer to be aligned to multiple of the texel size and 4 845cb93a386Sopenharmony_ci size_t alignment = bytesPerBlock; 846cb93a386Sopenharmony_ci switch (alignment & 0b11) { 847cb93a386Sopenharmony_ci case 0: break; // alignment is already a multiple of 4. 848cb93a386Sopenharmony_ci case 2: alignment *= 2; break; // alignment is a multiple of 2 but not 4. 849cb93a386Sopenharmony_ci default: alignment *= 4; break; // alignment is not a multiple of 2. 850cb93a386Sopenharmony_ci } 851cb93a386Sopenharmony_ci *slice = stagingBufferManager->allocateStagingBufferSlice(bufferSize, alignment); 852cb93a386Sopenharmony_ci if (!slice->fBuffer) { 853cb93a386Sopenharmony_ci return 0; 854cb93a386Sopenharmony_ci } 855cb93a386Sopenharmony_ci 856cb93a386Sopenharmony_ci for (int i = 0; i < numMipLevels; ++i) { 857cb93a386Sopenharmony_ci VkBufferImageCopy& region = regions->push_back(); 858cb93a386Sopenharmony_ci memset(®ion, 0, sizeof(VkBufferImageCopy)); 859cb93a386Sopenharmony_ci region.bufferOffset = slice->fOffset + (*individualMipOffsets)[i]; 860cb93a386Sopenharmony_ci SkISize revisedDimensions = GrCompressedDimensions(compression, dimensions); 861cb93a386Sopenharmony_ci region.bufferRowLength = revisedDimensions.width(); 862cb93a386Sopenharmony_ci region.bufferImageHeight = revisedDimensions.height(); 863cb93a386Sopenharmony_ci region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(i), 0, 1}; 864cb93a386Sopenharmony_ci region.imageOffset = {0, 0, 0}; 865cb93a386Sopenharmony_ci region.imageExtent = {SkToU32(dimensions.width()), 866cb93a386Sopenharmony_ci SkToU32(dimensions.height()), 1}; 867cb93a386Sopenharmony_ci 868cb93a386Sopenharmony_ci dimensions = {std::max(1, dimensions.width() /2), 869cb93a386Sopenharmony_ci std::max(1, dimensions.height()/2)}; 870cb93a386Sopenharmony_ci } 871cb93a386Sopenharmony_ci 872cb93a386Sopenharmony_ci return bufferSize; 873cb93a386Sopenharmony_ci} 874cb93a386Sopenharmony_ci 875cb93a386Sopenharmony_cistatic size_t fill_in_compressed_regions(SkTArray<VkBufferImageCopy>* regions, 876cb93a386Sopenharmony_ci SkTArray<size_t>* individualMipOffsets, 877cb93a386Sopenharmony_ci SkImage::CompressionType compression, 878cb93a386Sopenharmony_ci SkISize dimensions, 879cb93a386Sopenharmony_ci GrMipmapped mipmapped) { 880cb93a386Sopenharmony_ci SkASSERT(regions); 881cb93a386Sopenharmony_ci SkASSERT(individualMipOffsets); 882cb93a386Sopenharmony_ci SkASSERT(compression != SkImage::CompressionType::kNone); 883cb93a386Sopenharmony_ci 884cb93a386Sopenharmony_ci int mipmapLevelCount = 1; 885cb93a386Sopenharmony_ci if (mipmapped == GrMipmapped::kYes) { 886cb93a386Sopenharmony_ci mipmapLevelCount = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; 887cb93a386Sopenharmony_ci } 888cb93a386Sopenharmony_ci regions->reserve_back(mipmapLevelCount); 889cb93a386Sopenharmony_ci individualMipOffsets->reserve_back(mipmapLevelCount); 890cb93a386Sopenharmony_ci 891cb93a386Sopenharmony_ci size_t bufferSize = SkCompressedDataSize(compression, 892cb93a386Sopenharmony_ci dimensions, 893cb93a386Sopenharmony_ci individualMipOffsets, 894cb93a386Sopenharmony_ci mipmapped == GrMipmapped::kYes); 895cb93a386Sopenharmony_ci SkASSERT(individualMipOffsets->count() == mipmapLevelCount); 896cb93a386Sopenharmony_ci 897cb93a386Sopenharmony_ci for (int i = 0; i < mipmapLevelCount; ++i) { 898cb93a386Sopenharmony_ci VkBufferImageCopy ®ion = regions->push_back(); 899cb93a386Sopenharmony_ci region.bufferOffset = (*individualMipOffsets)[i]; 900cb93a386Sopenharmony_ci if (compression == SkImage::CompressionType::kASTC_RGBA8_4x4 || 901cb93a386Sopenharmony_ci compression == SkImage::CompressionType::kASTC_RGBA8_6x6 || 902cb93a386Sopenharmony_ci compression == SkImage::CompressionType::kASTC_RGBA8_8x8) { 903cb93a386Sopenharmony_ci region.bufferOffset += ASTC_HEADER_SIZE; 904cb93a386Sopenharmony_ci } 905cb93a386Sopenharmony_ci SkISize compressedDimensions = GrCompressedDimensions(compression, dimensions); 906cb93a386Sopenharmony_ci region.bufferRowLength = compressedDimensions.width(); 907cb93a386Sopenharmony_ci region.bufferImageHeight = compressedDimensions.height(); 908cb93a386Sopenharmony_ci region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(i), 0, 1}; 909cb93a386Sopenharmony_ci region.imageOffset = {0, 0, 0}; 910cb93a386Sopenharmony_ci region.imageExtent.width = SkToU32(dimensions.width()); 911cb93a386Sopenharmony_ci region.imageExtent.height = SkToU32(dimensions.height()); 912cb93a386Sopenharmony_ci region.imageExtent.depth = 1; 913cb93a386Sopenharmony_ci 914cb93a386Sopenharmony_ci dimensions = {std::max(1, dimensions.width() / 2), 915cb93a386Sopenharmony_ci std::max(1, dimensions.height() / 2)}; 916cb93a386Sopenharmony_ci } 917cb93a386Sopenharmony_ci 918cb93a386Sopenharmony_ci return bufferSize; 919cb93a386Sopenharmony_ci} 920cb93a386Sopenharmony_ci 921cb93a386Sopenharmony_cibool GrVkGpu::uploadTexDataOptimal(GrVkImage* texImage, 922cb93a386Sopenharmony_ci SkIRect rect, 923cb93a386Sopenharmony_ci GrColorType dataColorType, 924cb93a386Sopenharmony_ci const GrMipLevel texels[], 925cb93a386Sopenharmony_ci int mipLevelCount) { 926cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 927cb93a386Sopenharmony_ci return false; 928cb93a386Sopenharmony_ci } 929cb93a386Sopenharmony_ci 930cb93a386Sopenharmony_ci SkASSERT(!texImage->isLinearTiled()); 931cb93a386Sopenharmony_ci // The assumption is either that we have no mipmaps, or that our rect is the entire texture 932cb93a386Sopenharmony_ci SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(texImage->dimensions())); 933cb93a386Sopenharmony_ci 934cb93a386Sopenharmony_ci // We assume that if the texture has mip levels, we either upload to all the levels or just the 935cb93a386Sopenharmony_ci // first. 936cb93a386Sopenharmony_ci SkASSERT(mipLevelCount == 1 || mipLevelCount == (int)texImage->mipLevels()); 937cb93a386Sopenharmony_ci 938cb93a386Sopenharmony_ci SkASSERT(!rect.isEmpty()); 939cb93a386Sopenharmony_ci 940cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().surfaceSupportsWritePixels(texImage)); 941cb93a386Sopenharmony_ci 942cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().isVkFormatTexturable(texImage->imageFormat())); 943cb93a386Sopenharmony_ci size_t bpp = GrColorTypeBytesPerPixel(dataColorType); 944cb93a386Sopenharmony_ci 945cb93a386Sopenharmony_ci // texels is const. 946cb93a386Sopenharmony_ci // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes. 947cb93a386Sopenharmony_ci // Because of this we need to make a non-const shallow copy of texels. 948cb93a386Sopenharmony_ci SkAutoTArray<GrMipLevel> texelsShallowCopy(mipLevelCount); 949cb93a386Sopenharmony_ci std::copy_n(texels, mipLevelCount, texelsShallowCopy.get()); 950cb93a386Sopenharmony_ci 951cb93a386Sopenharmony_ci SkTArray<size_t> individualMipOffsets; 952cb93a386Sopenharmony_ci size_t combinedBufferSize; 953cb93a386Sopenharmony_ci if (mipLevelCount > 1) { 954cb93a386Sopenharmony_ci combinedBufferSize = GrComputeTightCombinedBufferSize(bpp, 955cb93a386Sopenharmony_ci rect.size(), 956cb93a386Sopenharmony_ci &individualMipOffsets, 957cb93a386Sopenharmony_ci mipLevelCount); 958cb93a386Sopenharmony_ci } else { 959cb93a386Sopenharmony_ci SkASSERT(texelsShallowCopy[0].fPixels && texelsShallowCopy[0].fRowBytes); 960cb93a386Sopenharmony_ci combinedBufferSize = rect.width()*rect.height()*bpp; 961cb93a386Sopenharmony_ci individualMipOffsets.push_back(0); 962cb93a386Sopenharmony_ci } 963cb93a386Sopenharmony_ci SkASSERT(combinedBufferSize); 964cb93a386Sopenharmony_ci 965cb93a386Sopenharmony_ci // Get a staging buffer slice to hold our mip data. 966cb93a386Sopenharmony_ci // Vulkan requires offsets in the buffer to be aligned to multiple of the texel size and 4 967cb93a386Sopenharmony_ci size_t alignment = bpp; 968cb93a386Sopenharmony_ci switch (alignment & 0b11) { 969cb93a386Sopenharmony_ci case 0: break; // alignment is already a multiple of 4. 970cb93a386Sopenharmony_ci case 2: alignment *= 2; break; // alignment is a multiple of 2 but not 4. 971cb93a386Sopenharmony_ci default: alignment *= 4; break; // alignment is not a multiple of 2. 972cb93a386Sopenharmony_ci } 973cb93a386Sopenharmony_ci GrStagingBufferManager::Slice slice = 974cb93a386Sopenharmony_ci fStagingBufferManager.allocateStagingBufferSlice(combinedBufferSize, alignment); 975cb93a386Sopenharmony_ci if (!slice.fBuffer) { 976cb93a386Sopenharmony_ci return false; 977cb93a386Sopenharmony_ci } 978cb93a386Sopenharmony_ci 979cb93a386Sopenharmony_ci int uploadLeft = rect.left(); 980cb93a386Sopenharmony_ci int uploadTop = rect.top(); 981cb93a386Sopenharmony_ci 982cb93a386Sopenharmony_ci char* buffer = (char*) slice.fOffsetMapPtr; 983cb93a386Sopenharmony_ci SkTArray<VkBufferImageCopy> regions(mipLevelCount); 984cb93a386Sopenharmony_ci 985cb93a386Sopenharmony_ci int currentWidth = rect.width(); 986cb93a386Sopenharmony_ci int currentHeight = rect.height(); 987cb93a386Sopenharmony_ci for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { 988cb93a386Sopenharmony_ci if (texelsShallowCopy[currentMipLevel].fPixels) { 989cb93a386Sopenharmony_ci const size_t trimRowBytes = currentWidth * bpp; 990cb93a386Sopenharmony_ci const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; 991cb93a386Sopenharmony_ci 992cb93a386Sopenharmony_ci // copy data into the buffer, skipping the trailing bytes 993cb93a386Sopenharmony_ci char* dst = buffer + individualMipOffsets[currentMipLevel]; 994cb93a386Sopenharmony_ci const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels; 995cb93a386Sopenharmony_ci SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight); 996cb93a386Sopenharmony_ci 997cb93a386Sopenharmony_ci VkBufferImageCopy& region = regions.push_back(); 998cb93a386Sopenharmony_ci memset(®ion, 0, sizeof(VkBufferImageCopy)); 999cb93a386Sopenharmony_ci region.bufferOffset = slice.fOffset + individualMipOffsets[currentMipLevel]; 1000cb93a386Sopenharmony_ci region.bufferRowLength = currentWidth; 1001cb93a386Sopenharmony_ci region.bufferImageHeight = currentHeight; 1002cb93a386Sopenharmony_ci region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1}; 1003cb93a386Sopenharmony_ci region.imageOffset = {uploadLeft, uploadTop, 0}; 1004cb93a386Sopenharmony_ci region.imageExtent = {(uint32_t)currentWidth, (uint32_t)currentHeight, 1}; 1005cb93a386Sopenharmony_ci } 1006cb93a386Sopenharmony_ci 1007cb93a386Sopenharmony_ci currentWidth = std::max(1, currentWidth/2); 1008cb93a386Sopenharmony_ci currentHeight = std::max(1, currentHeight/2); 1009cb93a386Sopenharmony_ci } 1010cb93a386Sopenharmony_ci 1011cb93a386Sopenharmony_ci // Change layout of our target so it can be copied to 1012cb93a386Sopenharmony_ci texImage->setImageLayout(this, 1013cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1014cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 1015cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 1016cb93a386Sopenharmony_ci false); 1017cb93a386Sopenharmony_ci 1018cb93a386Sopenharmony_ci // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer 1019cb93a386Sopenharmony_ci // because we don't need the command buffer to ref the buffer here. The reason being is that 1020cb93a386Sopenharmony_ci // the buffer is coming from the staging manager and the staging manager will make sure the 1021cb93a386Sopenharmony_ci // command buffer has a ref on the buffer. This avoids having to add and remove a ref for ever 1022cb93a386Sopenharmony_ci // upload in the frame. 1023cb93a386Sopenharmony_ci GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(slice.fBuffer); 1024cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyBufferToImage(this, 1025cb93a386Sopenharmony_ci vkBuffer->vkBuffer(), 1026cb93a386Sopenharmony_ci texImage, 1027cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1028cb93a386Sopenharmony_ci regions.count(), 1029cb93a386Sopenharmony_ci regions.begin()); 1030cb93a386Sopenharmony_ci return true; 1031cb93a386Sopenharmony_ci} 1032cb93a386Sopenharmony_ci 1033cb93a386Sopenharmony_ci// It's probably possible to roll this into uploadTexDataOptimal, 1034cb93a386Sopenharmony_ci// but for now it's easier to maintain as a separate entity. 1035cb93a386Sopenharmony_cibool GrVkGpu::uploadTexDataCompressed(GrVkImage* uploadTexture, 1036cb93a386Sopenharmony_ci SkImage::CompressionType compression, VkFormat vkFormat, 1037cb93a386Sopenharmony_ci SkISize dimensions, GrMipmapped mipMapped, 1038cb93a386Sopenharmony_ci const void* data, size_t dataSize) { 1039cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 1040cb93a386Sopenharmony_ci return false; 1041cb93a386Sopenharmony_ci } 1042cb93a386Sopenharmony_ci SkASSERT(data); 1043cb93a386Sopenharmony_ci SkASSERT(!uploadTexture->isLinearTiled()); 1044cb93a386Sopenharmony_ci // For now the assumption is that our rect is the entire texture. 1045cb93a386Sopenharmony_ci // Compressed textures are read-only so this should be a reasonable assumption. 1046cb93a386Sopenharmony_ci SkASSERT(dimensions.fWidth == uploadTexture->width() && 1047cb93a386Sopenharmony_ci dimensions.fHeight == uploadTexture->height()); 1048cb93a386Sopenharmony_ci 1049cb93a386Sopenharmony_ci if (dimensions.fWidth == 0 || dimensions.fHeight == 0) { 1050cb93a386Sopenharmony_ci return false; 1051cb93a386Sopenharmony_ci } 1052cb93a386Sopenharmony_ci 1053cb93a386Sopenharmony_ci SkASSERT(uploadTexture->imageFormat() == vkFormat); 1054cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().isVkFormatTexturable(vkFormat)); 1055cb93a386Sopenharmony_ci 1056cb93a386Sopenharmony_ci 1057cb93a386Sopenharmony_ci GrStagingBufferManager::Slice slice; 1058cb93a386Sopenharmony_ci SkTArray<VkBufferImageCopy> regions; 1059cb93a386Sopenharmony_ci SkTArray<size_t> individualMipOffsets; 1060cb93a386Sopenharmony_ci SkDEBUGCODE(size_t combinedBufferSize =) fill_in_compressed_regions(&fStagingBufferManager, 1061cb93a386Sopenharmony_ci ®ions, 1062cb93a386Sopenharmony_ci &individualMipOffsets, 1063cb93a386Sopenharmony_ci &slice, 1064cb93a386Sopenharmony_ci compression, 1065cb93a386Sopenharmony_ci vkFormat, 1066cb93a386Sopenharmony_ci dimensions, 1067cb93a386Sopenharmony_ci mipMapped); 1068cb93a386Sopenharmony_ci if (!slice.fBuffer) { 1069cb93a386Sopenharmony_ci return false; 1070cb93a386Sopenharmony_ci } 1071cb93a386Sopenharmony_ci SkASSERT(dataSize == combinedBufferSize); 1072cb93a386Sopenharmony_ci 1073cb93a386Sopenharmony_ci { 1074cb93a386Sopenharmony_ci char* buffer = (char*)slice.fOffsetMapPtr; 1075cb93a386Sopenharmony_ci memcpy(buffer, data, dataSize); 1076cb93a386Sopenharmony_ci } 1077cb93a386Sopenharmony_ci 1078cb93a386Sopenharmony_ci // Change layout of our target so it can be copied to 1079cb93a386Sopenharmony_ci uploadTexture->setImageLayout(this, 1080cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1081cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 1082cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 1083cb93a386Sopenharmony_ci false); 1084cb93a386Sopenharmony_ci 1085cb93a386Sopenharmony_ci // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer 1086cb93a386Sopenharmony_ci // because we don't need the command buffer to ref the buffer here. The reason being is that 1087cb93a386Sopenharmony_ci // the buffer is coming from the staging manager and the staging manager will make sure the 1088cb93a386Sopenharmony_ci // command buffer has a ref on the buffer. This avoids having to add and remove a ref for ever 1089cb93a386Sopenharmony_ci // upload in the frame. 1090cb93a386Sopenharmony_ci GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(slice.fBuffer); 1091cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyBufferToImage(this, 1092cb93a386Sopenharmony_ci vkBuffer->vkBuffer(), 1093cb93a386Sopenharmony_ci uploadTexture, 1094cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1095cb93a386Sopenharmony_ci regions.count(), 1096cb93a386Sopenharmony_ci regions.begin()); 1097cb93a386Sopenharmony_ci 1098cb93a386Sopenharmony_ci return true; 1099cb93a386Sopenharmony_ci} 1100cb93a386Sopenharmony_ci 1101cb93a386Sopenharmony_cibool GrVkGpu::uploadTexDataCompressed(GrVkImage* uploadTexture, 1102cb93a386Sopenharmony_ci SkImage::CompressionType compression, VkFormat vkFormat, 1103cb93a386Sopenharmony_ci SkISize dimensions, GrMipmapped mipMapped, 1104cb93a386Sopenharmony_ci OH_NativeBuffer* nativeBuffer, size_t bufferSize) { 1105cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 1106cb93a386Sopenharmony_ci return false; 1107cb93a386Sopenharmony_ci } 1108cb93a386Sopenharmony_ci SkASSERT(uploadTexture); 1109cb93a386Sopenharmony_ci SkASSERT(nativeBuffer); 1110cb93a386Sopenharmony_ci SkASSERT(!uploadTexture->isLinearTiled()); 1111cb93a386Sopenharmony_ci 1112cb93a386Sopenharmony_ci if (dimensions.width() == 0 || dimensions.height() == 0) { 1113cb93a386Sopenharmony_ci return false; 1114cb93a386Sopenharmony_ci } 1115cb93a386Sopenharmony_ci SkASSERT(dimensions.width() == uploadTexture->width() && dimensions.height() == uploadTexture->height()); 1116cb93a386Sopenharmony_ci 1117cb93a386Sopenharmony_ci SkASSERT(uploadTexture->imageFormat() == vkFormat); 1118cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().isVkFormatTexturable(vkFormat)); 1119cb93a386Sopenharmony_ci 1120cb93a386Sopenharmony_ci SkTArray<VkBufferImageCopy> regions; 1121cb93a386Sopenharmony_ci SkTArray<size_t> individualMipOffsets; 1122cb93a386Sopenharmony_ci SkDEBUGCODE(size_t combinedBufferSize =) fill_in_compressed_regions(®ions, &individualMipOffsets, 1123cb93a386Sopenharmony_ci compression, dimensions, mipMapped); 1124cb93a386Sopenharmony_ci SkASSERT(bufferSize == combinedBufferSize); 1125cb93a386Sopenharmony_ci 1126cb93a386Sopenharmony_ci // Import external memory. 1127cb93a386Sopenharmony_ci sk_sp<GrVkBuffer> vkBuffer = GrVkBuffer::MakeFromOHNativeBuffer(this, nativeBuffer, bufferSize, 1128cb93a386Sopenharmony_ci GrGpuBufferType::kXferCpuToGpu, 1129cb93a386Sopenharmony_ci kDynamic_GrAccessPattern); 1130cb93a386Sopenharmony_ci 1131cb93a386Sopenharmony_ci // Change image layout so it can be copied to. 1132cb93a386Sopenharmony_ci uploadTexture->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1133cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); 1134cb93a386Sopenharmony_ci 1135cb93a386Sopenharmony_ci // Copy the buffer to the image. 1136cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyBufferToImage(this, vkBuffer->vkBuffer(), uploadTexture, 1137cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1138cb93a386Sopenharmony_ci regions.count(), regions.begin()); 1139cb93a386Sopenharmony_ci this->takeOwnershipOfBuffer(std::move(vkBuffer)); 1140cb93a386Sopenharmony_ci 1141cb93a386Sopenharmony_ci return true; 1142cb93a386Sopenharmony_ci} 1143cb93a386Sopenharmony_ci 1144cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 1145cb93a386Sopenharmony_ci// TODO: make this take a GrMipmapped 1146cb93a386Sopenharmony_cisk_sp<GrTexture> GrVkGpu::onCreateTexture(SkISize dimensions, 1147cb93a386Sopenharmony_ci const GrBackendFormat& format, 1148cb93a386Sopenharmony_ci GrRenderable renderable, 1149cb93a386Sopenharmony_ci int renderTargetSampleCnt, 1150cb93a386Sopenharmony_ci SkBudgeted budgeted, 1151cb93a386Sopenharmony_ci GrProtected isProtected, 1152cb93a386Sopenharmony_ci int mipLevelCount, 1153cb93a386Sopenharmony_ci uint32_t levelClearMask) { 1154cb93a386Sopenharmony_ci VkFormat pixelFormat; 1155cb93a386Sopenharmony_ci SkAssertResult(format.asVkFormat(&pixelFormat)); 1156cb93a386Sopenharmony_ci SkASSERT(!GrVkFormatIsCompressed(pixelFormat)); 1157cb93a386Sopenharmony_ci SkASSERT(mipLevelCount > 0); 1158cb93a386Sopenharmony_ci 1159cb93a386Sopenharmony_ci HITRACE_OHOS_NAME_FMT_ALWAYS("onCreateTexture width = %d, height = %d", 1160cb93a386Sopenharmony_ci dimensions.width(), dimensions.height()); 1161cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus = 1162cb93a386Sopenharmony_ci mipLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated; 1163cb93a386Sopenharmony_ci 1164cb93a386Sopenharmony_ci sk_sp<GrVkTexture> tex; 1165cb93a386Sopenharmony_ci if (renderable == GrRenderable::kYes) { 1166cb93a386Sopenharmony_ci tex = GrVkTextureRenderTarget::MakeNewTextureRenderTarget( 1167cb93a386Sopenharmony_ci this, budgeted, dimensions, pixelFormat, mipLevelCount, renderTargetSampleCnt, 1168cb93a386Sopenharmony_ci mipmapStatus, isProtected); 1169cb93a386Sopenharmony_ci } else { 1170cb93a386Sopenharmony_ci tex = GrVkTexture::MakeNewTexture(this, budgeted, dimensions, pixelFormat, 1171cb93a386Sopenharmony_ci mipLevelCount, isProtected, mipmapStatus); 1172cb93a386Sopenharmony_ci } 1173cb93a386Sopenharmony_ci 1174cb93a386Sopenharmony_ci if (!tex) { 1175cb93a386Sopenharmony_ci return nullptr; 1176cb93a386Sopenharmony_ci } 1177cb93a386Sopenharmony_ci 1178cb93a386Sopenharmony_ci if (levelClearMask) { 1179cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 1180cb93a386Sopenharmony_ci return nullptr; 1181cb93a386Sopenharmony_ci } 1182cb93a386Sopenharmony_ci SkSTArray<1, VkImageSubresourceRange> ranges; 1183cb93a386Sopenharmony_ci bool inRange = false; 1184cb93a386Sopenharmony_ci GrVkImage* texImage = tex->textureImage(); 1185cb93a386Sopenharmony_ci for (uint32_t i = 0; i < texImage->mipLevels(); ++i) { 1186cb93a386Sopenharmony_ci if (levelClearMask & (1U << i)) { 1187cb93a386Sopenharmony_ci if (inRange) { 1188cb93a386Sopenharmony_ci ranges.back().levelCount++; 1189cb93a386Sopenharmony_ci } else { 1190cb93a386Sopenharmony_ci auto& range = ranges.push_back(); 1191cb93a386Sopenharmony_ci range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1192cb93a386Sopenharmony_ci range.baseArrayLayer = 0; 1193cb93a386Sopenharmony_ci range.baseMipLevel = i; 1194cb93a386Sopenharmony_ci range.layerCount = 1; 1195cb93a386Sopenharmony_ci range.levelCount = 1; 1196cb93a386Sopenharmony_ci inRange = true; 1197cb93a386Sopenharmony_ci } 1198cb93a386Sopenharmony_ci } else if (inRange) { 1199cb93a386Sopenharmony_ci inRange = false; 1200cb93a386Sopenharmony_ci } 1201cb93a386Sopenharmony_ci } 1202cb93a386Sopenharmony_ci SkASSERT(!ranges.empty()); 1203cb93a386Sopenharmony_ci static constexpr VkClearColorValue kZeroClearColor = {}; 1204cb93a386Sopenharmony_ci texImage->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1205cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); 1206cb93a386Sopenharmony_ci this->currentCommandBuffer()->clearColorImage(this, texImage, &kZeroClearColor, 1207cb93a386Sopenharmony_ci ranges.count(), ranges.begin()); 1208cb93a386Sopenharmony_ci } 1209cb93a386Sopenharmony_ci return std::move(tex); 1210cb93a386Sopenharmony_ci} 1211cb93a386Sopenharmony_ci 1212cb93a386Sopenharmony_cisk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions, 1213cb93a386Sopenharmony_ci const GrBackendFormat& format, 1214cb93a386Sopenharmony_ci SkBudgeted budgeted, 1215cb93a386Sopenharmony_ci GrMipmapped mipMapped, 1216cb93a386Sopenharmony_ci GrProtected isProtected, 1217cb93a386Sopenharmony_ci const void* data, size_t dataSize) { 1218cb93a386Sopenharmony_ci VkFormat pixelFormat; 1219cb93a386Sopenharmony_ci SkAssertResult(format.asVkFormat(&pixelFormat)); 1220cb93a386Sopenharmony_ci SkASSERT(GrVkFormatIsCompressed(pixelFormat)); 1221cb93a386Sopenharmony_ci 1222cb93a386Sopenharmony_ci int numMipLevels = 1; 1223cb93a386Sopenharmony_ci if (mipMapped == GrMipmapped::kYes) { 1224cb93a386Sopenharmony_ci numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height())+1; 1225cb93a386Sopenharmony_ci } 1226cb93a386Sopenharmony_ci 1227cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus = (mipMapped == GrMipmapped::kYes) ? GrMipmapStatus::kValid 1228cb93a386Sopenharmony_ci : GrMipmapStatus::kNotAllocated; 1229cb93a386Sopenharmony_ci 1230cb93a386Sopenharmony_ci auto tex = GrVkTexture::MakeNewTexture(this, budgeted, dimensions, pixelFormat, 1231cb93a386Sopenharmony_ci numMipLevels, isProtected, mipmapStatus); 1232cb93a386Sopenharmony_ci if (!tex) { 1233cb93a386Sopenharmony_ci return nullptr; 1234cb93a386Sopenharmony_ci } 1235cb93a386Sopenharmony_ci 1236cb93a386Sopenharmony_ci SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); 1237cb93a386Sopenharmony_ci if (!this->uploadTexDataCompressed(tex->textureImage(), compression, pixelFormat, 1238cb93a386Sopenharmony_ci dimensions, mipMapped, data, dataSize)) { 1239cb93a386Sopenharmony_ci return nullptr; 1240cb93a386Sopenharmony_ci } 1241cb93a386Sopenharmony_ci 1242cb93a386Sopenharmony_ci return std::move(tex); 1243cb93a386Sopenharmony_ci} 1244cb93a386Sopenharmony_ci 1245cb93a386Sopenharmony_cisk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions, 1246cb93a386Sopenharmony_ci const GrBackendFormat& format, 1247cb93a386Sopenharmony_ci SkBudgeted budgeted, 1248cb93a386Sopenharmony_ci GrMipmapped mipMapped, 1249cb93a386Sopenharmony_ci GrProtected isProtected, 1250cb93a386Sopenharmony_ci OH_NativeBuffer* nativeBuffer, 1251cb93a386Sopenharmony_ci size_t bufferSize) { 1252cb93a386Sopenharmony_ci VkFormat pixelFormat; 1253cb93a386Sopenharmony_ci SkAssertResult(format.asVkFormat(&pixelFormat)); 1254cb93a386Sopenharmony_ci SkASSERT(GrVkFormatIsCompressed(pixelFormat)); 1255cb93a386Sopenharmony_ci 1256cb93a386Sopenharmony_ci int mipmapLevelCount = 1; 1257cb93a386Sopenharmony_ci GrMipmapStatus mipmapStatus = GrMipmapStatus::kNotAllocated; 1258cb93a386Sopenharmony_ci if (mipMapped == GrMipmapped::kYes) { 1259cb93a386Sopenharmony_ci mipmapLevelCount = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; 1260cb93a386Sopenharmony_ci mipmapStatus = GrMipmapStatus::kValid; 1261cb93a386Sopenharmony_ci } 1262cb93a386Sopenharmony_ci 1263cb93a386Sopenharmony_ci sk_sp<GrVkTexture> texture = GrVkTexture::MakeNewTexture(this, budgeted, dimensions, pixelFormat, 1264cb93a386Sopenharmony_ci mipmapLevelCount, isProtected, mipmapStatus); 1265cb93a386Sopenharmony_ci if (!texture) { 1266cb93a386Sopenharmony_ci return nullptr; 1267cb93a386Sopenharmony_ci } 1268cb93a386Sopenharmony_ci 1269cb93a386Sopenharmony_ci SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); 1270cb93a386Sopenharmony_ci if (!this->uploadTexDataCompressed(texture->textureImage(), compression, pixelFormat, 1271cb93a386Sopenharmony_ci dimensions, mipMapped, nativeBuffer, bufferSize)) { 1272cb93a386Sopenharmony_ci return nullptr; 1273cb93a386Sopenharmony_ci } 1274cb93a386Sopenharmony_ci 1275cb93a386Sopenharmony_ci return std::move(texture); 1276cb93a386Sopenharmony_ci} 1277cb93a386Sopenharmony_ci 1278cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 1279cb93a386Sopenharmony_ci 1280cb93a386Sopenharmony_civoid GrVkGpu::copyBuffer(sk_sp<GrGpuBuffer> srcBuffer, 1281cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> dstBuffer, 1282cb93a386Sopenharmony_ci VkDeviceSize srcOffset, 1283cb93a386Sopenharmony_ci VkDeviceSize dstOffset, 1284cb93a386Sopenharmony_ci VkDeviceSize size) { 1285cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 1286cb93a386Sopenharmony_ci return; 1287cb93a386Sopenharmony_ci } 1288cb93a386Sopenharmony_ci VkBufferCopy copyRegion; 1289cb93a386Sopenharmony_ci copyRegion.srcOffset = srcOffset; 1290cb93a386Sopenharmony_ci copyRegion.dstOffset = dstOffset; 1291cb93a386Sopenharmony_ci copyRegion.size = size; 1292cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyBuffer(this, std::move(srcBuffer), std::move(dstBuffer), 1, 1293cb93a386Sopenharmony_ci ©Region); 1294cb93a386Sopenharmony_ci} 1295cb93a386Sopenharmony_ci 1296cb93a386Sopenharmony_cibool GrVkGpu::updateBuffer(sk_sp<GrVkBuffer> buffer, const void* src, 1297cb93a386Sopenharmony_ci VkDeviceSize offset, VkDeviceSize size) { 1298cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 1299cb93a386Sopenharmony_ci return false; 1300cb93a386Sopenharmony_ci } 1301cb93a386Sopenharmony_ci // Update the buffer 1302cb93a386Sopenharmony_ci this->currentCommandBuffer()->updateBuffer(this, std::move(buffer), offset, size, src); 1303cb93a386Sopenharmony_ci 1304cb93a386Sopenharmony_ci return true; 1305cb93a386Sopenharmony_ci} 1306cb93a386Sopenharmony_ci 1307cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 1308cb93a386Sopenharmony_ci 1309cb93a386Sopenharmony_cistatic bool check_image_info(const GrVkCaps& caps, 1310cb93a386Sopenharmony_ci const GrVkImageInfo& info, 1311cb93a386Sopenharmony_ci bool needsAllocation, 1312cb93a386Sopenharmony_ci uint32_t graphicsQueueIndex) { 1313cb93a386Sopenharmony_ci if (VK_NULL_HANDLE == info.fImage) { 1314cb93a386Sopenharmony_ci return false; 1315cb93a386Sopenharmony_ci } 1316cb93a386Sopenharmony_ci 1317cb93a386Sopenharmony_ci if (VK_NULL_HANDLE == info.fAlloc.fMemory && needsAllocation) { 1318cb93a386Sopenharmony_ci return false; 1319cb93a386Sopenharmony_ci } 1320cb93a386Sopenharmony_ci 1321cb93a386Sopenharmony_ci if (info.fImageLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && !caps.supportsSwapchain()) { 1322cb93a386Sopenharmony_ci return false; 1323cb93a386Sopenharmony_ci } 1324cb93a386Sopenharmony_ci 1325cb93a386Sopenharmony_ci if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED && 1326cb93a386Sopenharmony_ci info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL && 1327cb93a386Sopenharmony_ci info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) { 1328cb93a386Sopenharmony_ci if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) { 1329cb93a386Sopenharmony_ci if (info.fCurrentQueueFamily != graphicsQueueIndex) { 1330cb93a386Sopenharmony_ci return false; 1331cb93a386Sopenharmony_ci } 1332cb93a386Sopenharmony_ci } else { 1333cb93a386Sopenharmony_ci return false; 1334cb93a386Sopenharmony_ci } 1335cb93a386Sopenharmony_ci } 1336cb93a386Sopenharmony_ci 1337cb93a386Sopenharmony_ci if (info.fYcbcrConversionInfo.isValid()) { 1338cb93a386Sopenharmony_ci if (!caps.supportsYcbcrConversion()) { 1339cb93a386Sopenharmony_ci return false; 1340cb93a386Sopenharmony_ci } 1341cb93a386Sopenharmony_ci if (info.fYcbcrConversionInfo.fExternalFormat != 0) { 1342cb93a386Sopenharmony_ci return true; 1343cb93a386Sopenharmony_ci } 1344cb93a386Sopenharmony_ci } 1345cb93a386Sopenharmony_ci 1346cb93a386Sopenharmony_ci // We currently require everything to be made with transfer bits set 1347cb93a386Sopenharmony_ci if (!SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) || 1348cb93a386Sopenharmony_ci !SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) { 1349cb93a386Sopenharmony_ci return false; 1350cb93a386Sopenharmony_ci } 1351cb93a386Sopenharmony_ci 1352cb93a386Sopenharmony_ci return true; 1353cb93a386Sopenharmony_ci} 1354cb93a386Sopenharmony_ci 1355cb93a386Sopenharmony_cistatic bool check_tex_image_info(const GrVkCaps& caps, const GrVkImageInfo& info) { 1356cb93a386Sopenharmony_ci // We don't support directly importing multisampled textures for sampling from shaders. 1357cb93a386Sopenharmony_ci if (info.fSampleCount != 1) { 1358cb93a386Sopenharmony_ci return false; 1359cb93a386Sopenharmony_ci } 1360cb93a386Sopenharmony_ci 1361cb93a386Sopenharmony_ci if (info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) { 1362cb93a386Sopenharmony_ci return true; 1363cb93a386Sopenharmony_ci } 1364cb93a386Sopenharmony_ci if (info.fImageTiling == VK_IMAGE_TILING_OPTIMAL) { 1365cb93a386Sopenharmony_ci if (!caps.isVkFormatTexturable(info.fFormat)) { 1366cb93a386Sopenharmony_ci return false; 1367cb93a386Sopenharmony_ci } 1368cb93a386Sopenharmony_ci } else if (info.fImageTiling == VK_IMAGE_TILING_LINEAR) { 1369cb93a386Sopenharmony_ci if (!caps.isVkFormatTexturableLinearly(info.fFormat)) { 1370cb93a386Sopenharmony_ci return false; 1371cb93a386Sopenharmony_ci } 1372cb93a386Sopenharmony_ci } else if (info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { 1373cb93a386Sopenharmony_ci if (!caps.supportsDRMFormatModifiers()) { 1374cb93a386Sopenharmony_ci return false; 1375cb93a386Sopenharmony_ci } 1376cb93a386Sopenharmony_ci // To be technically correct we should query the vulkan support for VkFormat and 1377cb93a386Sopenharmony_ci // drmFormatModifier pairs to confirm the required feature support is there. However, we 1378cb93a386Sopenharmony_ci // currently don't have our caps and format tables set up to do this effeciently. So 1379cb93a386Sopenharmony_ci // instead we just rely on the client's passed in VkImageUsageFlags and assume they we set 1380cb93a386Sopenharmony_ci // up using valid features (checked below). In practice this should all be safe because 1381cb93a386Sopenharmony_ci // currently we are setting all drm format modifier textures to have a 1382cb93a386Sopenharmony_ci // GrTextureType::kExternal so we just really need to be able to read these video VkImage in 1383cb93a386Sopenharmony_ci // a shader. The video decoder isn't going to give us VkImages that don't support being 1384cb93a386Sopenharmony_ci // sampled. 1385cb93a386Sopenharmony_ci } else { 1386cb93a386Sopenharmony_ci SkUNREACHABLE; 1387cb93a386Sopenharmony_ci } 1388cb93a386Sopenharmony_ci 1389cb93a386Sopenharmony_ci // We currently require all textures to be made with sample support 1390cb93a386Sopenharmony_ci if (!SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)) { 1391cb93a386Sopenharmony_ci return false; 1392cb93a386Sopenharmony_ci } 1393cb93a386Sopenharmony_ci 1394cb93a386Sopenharmony_ci return true; 1395cb93a386Sopenharmony_ci} 1396cb93a386Sopenharmony_ci 1397cb93a386Sopenharmony_cistatic bool check_rt_image_info(const GrVkCaps& caps, const GrVkImageInfo& info, bool resolveOnly) { 1398cb93a386Sopenharmony_ci if (!caps.isFormatRenderable(info.fFormat, info.fSampleCount)) { 1399cb93a386Sopenharmony_ci return false; 1400cb93a386Sopenharmony_ci } 1401cb93a386Sopenharmony_ci if (!resolveOnly && !SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) { 1402cb93a386Sopenharmony_ci return false; 1403cb93a386Sopenharmony_ci } 1404cb93a386Sopenharmony_ci return true; 1405cb93a386Sopenharmony_ci} 1406cb93a386Sopenharmony_ci 1407cb93a386Sopenharmony_cisk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTex, 1408cb93a386Sopenharmony_ci GrWrapOwnership ownership, 1409cb93a386Sopenharmony_ci GrWrapCacheable cacheable, 1410cb93a386Sopenharmony_ci GrIOType ioType) { 1411cb93a386Sopenharmony_ci GrVkImageInfo imageInfo; 1412cb93a386Sopenharmony_ci if (!backendTex.getVkImageInfo(&imageInfo)) { 1413cb93a386Sopenharmony_ci return nullptr; 1414cb93a386Sopenharmony_ci } 1415cb93a386Sopenharmony_ci 1416cb93a386Sopenharmony_ci if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership, 1417cb93a386Sopenharmony_ci this->queueIndex())) { 1418cb93a386Sopenharmony_ci return nullptr; 1419cb93a386Sopenharmony_ci } 1420cb93a386Sopenharmony_ci 1421cb93a386Sopenharmony_ci if (!check_tex_image_info(this->vkCaps(), imageInfo)) { 1422cb93a386Sopenharmony_ci return nullptr; 1423cb93a386Sopenharmony_ci } 1424cb93a386Sopenharmony_ci 1425cb93a386Sopenharmony_ci if (backendTex.isProtected() && (fProtectedContext == GrProtected::kNo)) { 1426cb93a386Sopenharmony_ci return nullptr; 1427cb93a386Sopenharmony_ci } 1428cb93a386Sopenharmony_ci 1429cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTex.getMutableState(); 1430cb93a386Sopenharmony_ci SkASSERT(mutableState); 1431cb93a386Sopenharmony_ci return GrVkTexture::MakeWrappedTexture(this, backendTex.dimensions(), ownership, cacheable, 1432cb93a386Sopenharmony_ci ioType, imageInfo, std::move(mutableState)); 1433cb93a386Sopenharmony_ci} 1434cb93a386Sopenharmony_ci 1435cb93a386Sopenharmony_cisk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture& beTex, 1436cb93a386Sopenharmony_ci GrWrapOwnership ownership, 1437cb93a386Sopenharmony_ci GrWrapCacheable cacheable) { 1438cb93a386Sopenharmony_ci return this->onWrapBackendTexture(beTex, ownership, cacheable, kRead_GrIOType); 1439cb93a386Sopenharmony_ci} 1440cb93a386Sopenharmony_ci 1441cb93a386Sopenharmony_cisk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex, 1442cb93a386Sopenharmony_ci int sampleCnt, 1443cb93a386Sopenharmony_ci GrWrapOwnership ownership, 1444cb93a386Sopenharmony_ci GrWrapCacheable cacheable) { 1445cb93a386Sopenharmony_ci GrVkImageInfo imageInfo; 1446cb93a386Sopenharmony_ci if (!backendTex.getVkImageInfo(&imageInfo)) { 1447cb93a386Sopenharmony_ci return nullptr; 1448cb93a386Sopenharmony_ci } 1449cb93a386Sopenharmony_ci 1450cb93a386Sopenharmony_ci if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership, 1451cb93a386Sopenharmony_ci this->queueIndex())) { 1452cb93a386Sopenharmony_ci return nullptr; 1453cb93a386Sopenharmony_ci } 1454cb93a386Sopenharmony_ci 1455cb93a386Sopenharmony_ci if (!check_tex_image_info(this->vkCaps(), imageInfo)) { 1456cb93a386Sopenharmony_ci return nullptr; 1457cb93a386Sopenharmony_ci } 1458cb93a386Sopenharmony_ci // If sampleCnt is > 1 we will create an intermediate MSAA VkImage and then resolve into 1459cb93a386Sopenharmony_ci // the wrapped VkImage. 1460cb93a386Sopenharmony_ci bool resolveOnly = sampleCnt > 1; 1461cb93a386Sopenharmony_ci if (!check_rt_image_info(this->vkCaps(), imageInfo, resolveOnly)) { 1462cb93a386Sopenharmony_ci return nullptr; 1463cb93a386Sopenharmony_ci } 1464cb93a386Sopenharmony_ci 1465cb93a386Sopenharmony_ci if (backendTex.isProtected() && (fProtectedContext == GrProtected::kNo)) { 1466cb93a386Sopenharmony_ci return nullptr; 1467cb93a386Sopenharmony_ci } 1468cb93a386Sopenharmony_ci 1469cb93a386Sopenharmony_ci sampleCnt = this->vkCaps().getRenderTargetSampleCount(sampleCnt, imageInfo.fFormat); 1470cb93a386Sopenharmony_ci 1471cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTex.getMutableState(); 1472cb93a386Sopenharmony_ci SkASSERT(mutableState); 1473cb93a386Sopenharmony_ci 1474cb93a386Sopenharmony_ci return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, backendTex.dimensions(), 1475cb93a386Sopenharmony_ci sampleCnt, ownership, cacheable, 1476cb93a386Sopenharmony_ci imageInfo, 1477cb93a386Sopenharmony_ci std::move(mutableState)); 1478cb93a386Sopenharmony_ci} 1479cb93a386Sopenharmony_ci 1480cb93a386Sopenharmony_cisk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) { 1481cb93a386Sopenharmony_ci GrVkImageInfo info; 1482cb93a386Sopenharmony_ci if (!backendRT.getVkImageInfo(&info)) { 1483cb93a386Sopenharmony_ci return nullptr; 1484cb93a386Sopenharmony_ci } 1485cb93a386Sopenharmony_ci 1486cb93a386Sopenharmony_ci if (!check_image_info(this->vkCaps(), info, false, this->queueIndex())) { 1487cb93a386Sopenharmony_ci return nullptr; 1488cb93a386Sopenharmony_ci } 1489cb93a386Sopenharmony_ci 1490cb93a386Sopenharmony_ci // We will always render directly to this VkImage. 1491cb93a386Sopenharmony_ci static bool kResolveOnly = false; 1492cb93a386Sopenharmony_ci if (!check_rt_image_info(this->vkCaps(), info, kResolveOnly)) { 1493cb93a386Sopenharmony_ci return nullptr; 1494cb93a386Sopenharmony_ci } 1495cb93a386Sopenharmony_ci 1496cb93a386Sopenharmony_ci if (backendRT.isProtected() && (fProtectedContext == GrProtected::kNo)) { 1497cb93a386Sopenharmony_ci return nullptr; 1498cb93a386Sopenharmony_ci } 1499cb93a386Sopenharmony_ci 1500cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendRT.getMutableState(); 1501cb93a386Sopenharmony_ci SkASSERT(mutableState); 1502cb93a386Sopenharmony_ci 1503cb93a386Sopenharmony_ci sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget( 1504cb93a386Sopenharmony_ci this, backendRT.dimensions(), backendRT.sampleCnt(), info, std::move(mutableState)); 1505cb93a386Sopenharmony_ci 1506cb93a386Sopenharmony_ci // We don't allow the client to supply a premade stencil buffer. We always create one if needed. 1507cb93a386Sopenharmony_ci SkASSERT(!backendRT.stencilBits()); 1508cb93a386Sopenharmony_ci if (tgt) { 1509cb93a386Sopenharmony_ci SkASSERT(tgt->canAttemptStencilAttachment(tgt->numSamples() > 1)); 1510cb93a386Sopenharmony_ci } 1511cb93a386Sopenharmony_ci 1512cb93a386Sopenharmony_ci return std::move(tgt); 1513cb93a386Sopenharmony_ci} 1514cb93a386Sopenharmony_ci 1515cb93a386Sopenharmony_cisk_sp<GrRenderTarget> GrVkGpu::onWrapVulkanSecondaryCBAsRenderTarget( 1516cb93a386Sopenharmony_ci const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) { 1517cb93a386Sopenharmony_ci int maxSize = this->caps()->maxTextureSize(); 1518cb93a386Sopenharmony_ci if (imageInfo.width() > maxSize || imageInfo.height() > maxSize) { 1519cb93a386Sopenharmony_ci return nullptr; 1520cb93a386Sopenharmony_ci } 1521cb93a386Sopenharmony_ci 1522cb93a386Sopenharmony_ci GrBackendFormat backendFormat = GrBackendFormat::MakeVk(vkInfo.fFormat); 1523cb93a386Sopenharmony_ci if (!backendFormat.isValid()) { 1524cb93a386Sopenharmony_ci return nullptr; 1525cb93a386Sopenharmony_ci } 1526cb93a386Sopenharmony_ci int sampleCnt = this->vkCaps().getRenderTargetSampleCount(1, vkInfo.fFormat); 1527cb93a386Sopenharmony_ci if (!sampleCnt) { 1528cb93a386Sopenharmony_ci return nullptr; 1529cb93a386Sopenharmony_ci } 1530cb93a386Sopenharmony_ci 1531cb93a386Sopenharmony_ci return GrVkRenderTarget::MakeSecondaryCBRenderTarget(this, imageInfo.dimensions(), vkInfo); 1532cb93a386Sopenharmony_ci} 1533cb93a386Sopenharmony_ci 1534cb93a386Sopenharmony_cibool GrVkGpu::loadMSAAFromResolve(GrVkCommandBuffer* commandBuffer, 1535cb93a386Sopenharmony_ci const GrVkRenderPass& renderPass, 1536cb93a386Sopenharmony_ci GrAttachment* dst, 1537cb93a386Sopenharmony_ci GrVkImage* src, 1538cb93a386Sopenharmony_ci const SkIRect& srcRect) { 1539cb93a386Sopenharmony_ci return fMSAALoadManager.loadMSAAFromResolve(this, commandBuffer, renderPass, dst, src, srcRect); 1540cb93a386Sopenharmony_ci} 1541cb93a386Sopenharmony_ci 1542cb93a386Sopenharmony_cibool GrVkGpu::onRegenerateMipMapLevels(GrTexture* tex) { 1543cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 1544cb93a386Sopenharmony_ci return false; 1545cb93a386Sopenharmony_ci } 1546cb93a386Sopenharmony_ci auto* vkTex = static_cast<GrVkTexture*>(tex)->textureImage(); 1547cb93a386Sopenharmony_ci // don't do anything for linearly tiled textures (can't have mipmaps) 1548cb93a386Sopenharmony_ci if (vkTex->isLinearTiled()) { 1549cb93a386Sopenharmony_ci SkDebugf("Trying to create mipmap for linear tiled texture"); 1550cb93a386Sopenharmony_ci return false; 1551cb93a386Sopenharmony_ci } 1552cb93a386Sopenharmony_ci SkASSERT(tex->textureType() == GrTextureType::k2D); 1553cb93a386Sopenharmony_ci 1554cb93a386Sopenharmony_ci // determine if we can blit to and from this format 1555cb93a386Sopenharmony_ci const GrVkCaps& caps = this->vkCaps(); 1556cb93a386Sopenharmony_ci if (!caps.formatCanBeDstofBlit(vkTex->imageFormat(), false) || 1557cb93a386Sopenharmony_ci !caps.formatCanBeSrcofBlit(vkTex->imageFormat(), false) || 1558cb93a386Sopenharmony_ci !caps.mipmapSupport()) { 1559cb93a386Sopenharmony_ci return false; 1560cb93a386Sopenharmony_ci } 1561cb93a386Sopenharmony_ci 1562cb93a386Sopenharmony_ci int width = tex->width(); 1563cb93a386Sopenharmony_ci int height = tex->height(); 1564cb93a386Sopenharmony_ci VkImageBlit blitRegion; 1565cb93a386Sopenharmony_ci memset(&blitRegion, 0, sizeof(VkImageBlit)); 1566cb93a386Sopenharmony_ci 1567cb93a386Sopenharmony_ci // SkMipmap doesn't include the base level in the level count so we have to add 1 1568cb93a386Sopenharmony_ci uint32_t levelCount = SkMipmap::ComputeLevelCount(tex->width(), tex->height()) + 1; 1569cb93a386Sopenharmony_ci SkASSERT(levelCount == vkTex->mipLevels()); 1570cb93a386Sopenharmony_ci 1571cb93a386Sopenharmony_ci // change layout of the layers so we can write to them. 1572cb93a386Sopenharmony_ci vkTex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, 1573cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, false); 1574cb93a386Sopenharmony_ci 1575cb93a386Sopenharmony_ci // setup memory barrier 1576cb93a386Sopenharmony_ci SkASSERT(GrVkFormatIsSupported(vkTex->imageFormat())); 1577cb93a386Sopenharmony_ci VkImageMemoryBarrier imageMemoryBarrier = { 1578cb93a386Sopenharmony_ci VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 1579cb93a386Sopenharmony_ci nullptr, // pNext 1580cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask 1581cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask 1582cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // oldLayout 1583cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout 1584cb93a386Sopenharmony_ci VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 1585cb93a386Sopenharmony_ci VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex 1586cb93a386Sopenharmony_ci vkTex->image(), // image 1587cb93a386Sopenharmony_ci {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange 1588cb93a386Sopenharmony_ci }; 1589cb93a386Sopenharmony_ci 1590cb93a386Sopenharmony_ci // Blit the miplevels 1591cb93a386Sopenharmony_ci uint32_t mipLevel = 1; 1592cb93a386Sopenharmony_ci while (mipLevel < levelCount) { 1593cb93a386Sopenharmony_ci int prevWidth = width; 1594cb93a386Sopenharmony_ci int prevHeight = height; 1595cb93a386Sopenharmony_ci width = std::max(1, width / 2); 1596cb93a386Sopenharmony_ci height = std::max(1, height / 2); 1597cb93a386Sopenharmony_ci 1598cb93a386Sopenharmony_ci imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1; 1599cb93a386Sopenharmony_ci this->addImageMemoryBarrier(vkTex->resource(), VK_PIPELINE_STAGE_TRANSFER_BIT, 1600cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, false, &imageMemoryBarrier); 1601cb93a386Sopenharmony_ci 1602cb93a386Sopenharmony_ci blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 }; 1603cb93a386Sopenharmony_ci blitRegion.srcOffsets[0] = { 0, 0, 0 }; 1604cb93a386Sopenharmony_ci blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 }; 1605cb93a386Sopenharmony_ci blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 }; 1606cb93a386Sopenharmony_ci blitRegion.dstOffsets[0] = { 0, 0, 0 }; 1607cb93a386Sopenharmony_ci blitRegion.dstOffsets[1] = { width, height, 1 }; 1608cb93a386Sopenharmony_ci this->currentCommandBuffer()->blitImage(this, 1609cb93a386Sopenharmony_ci vkTex->resource(), 1610cb93a386Sopenharmony_ci vkTex->image(), 1611cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1612cb93a386Sopenharmony_ci vkTex->resource(), 1613cb93a386Sopenharmony_ci vkTex->image(), 1614cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1615cb93a386Sopenharmony_ci 1, 1616cb93a386Sopenharmony_ci &blitRegion, 1617cb93a386Sopenharmony_ci VK_FILTER_LINEAR); 1618cb93a386Sopenharmony_ci ++mipLevel; 1619cb93a386Sopenharmony_ci } 1620cb93a386Sopenharmony_ci if (levelCount > 1) { 1621cb93a386Sopenharmony_ci // This barrier logically is not needed, but it changes the final level to the same layout 1622cb93a386Sopenharmony_ci // as all the others, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL. This makes tracking of the 1623cb93a386Sopenharmony_ci // layouts and future layout changes easier. The alternative here would be to track layout 1624cb93a386Sopenharmony_ci // and memory accesses per layer which doesn't seem work it. 1625cb93a386Sopenharmony_ci imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1; 1626cb93a386Sopenharmony_ci this->addImageMemoryBarrier(vkTex->resource(), VK_PIPELINE_STAGE_TRANSFER_BIT, 1627cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, false, &imageMemoryBarrier); 1628cb93a386Sopenharmony_ci vkTex->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 1629cb93a386Sopenharmony_ci } 1630cb93a386Sopenharmony_ci return true; 1631cb93a386Sopenharmony_ci} 1632cb93a386Sopenharmony_ci 1633cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 1634cb93a386Sopenharmony_ci 1635cb93a386Sopenharmony_cisk_sp<GrAttachment> GrVkGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/, 1636cb93a386Sopenharmony_ci SkISize dimensions, int numStencilSamples) { 1637cb93a386Sopenharmony_ci VkFormat sFmt = this->vkCaps().preferredStencilFormat(); 1638cb93a386Sopenharmony_ci 1639cb93a386Sopenharmony_ci fStats.incStencilAttachmentCreates(); 1640cb93a386Sopenharmony_ci return GrVkImage::MakeStencil(this, dimensions, numStencilSamples, sFmt); 1641cb93a386Sopenharmony_ci} 1642cb93a386Sopenharmony_ci 1643cb93a386Sopenharmony_cisk_sp<GrAttachment> GrVkGpu::makeMSAAAttachment(SkISize dimensions, 1644cb93a386Sopenharmony_ci const GrBackendFormat& format, 1645cb93a386Sopenharmony_ci int numSamples, 1646cb93a386Sopenharmony_ci GrProtected isProtected, 1647cb93a386Sopenharmony_ci GrMemoryless memoryless) { 1648cb93a386Sopenharmony_ci VkFormat pixelFormat; 1649cb93a386Sopenharmony_ci SkAssertResult(format.asVkFormat(&pixelFormat)); 1650cb93a386Sopenharmony_ci SkASSERT(!GrVkFormatIsCompressed(pixelFormat)); 1651cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().isFormatRenderable(pixelFormat, numSamples)); 1652cb93a386Sopenharmony_ci 1653cb93a386Sopenharmony_ci fStats.incMSAAAttachmentCreates(); 1654cb93a386Sopenharmony_ci return GrVkImage::MakeMSAA(this, dimensions, numSamples, pixelFormat, isProtected, memoryless); 1655cb93a386Sopenharmony_ci} 1656cb93a386Sopenharmony_ci 1657cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 1658cb93a386Sopenharmony_ci 1659cb93a386Sopenharmony_cibool copy_src_data(char* mapPtr, 1660cb93a386Sopenharmony_ci VkFormat vkFormat, 1661cb93a386Sopenharmony_ci const SkTArray<size_t>& individualMipOffsets, 1662cb93a386Sopenharmony_ci const GrPixmap srcData[], 1663cb93a386Sopenharmony_ci int numMipLevels) { 1664cb93a386Sopenharmony_ci SkASSERT(srcData && numMipLevels); 1665cb93a386Sopenharmony_ci SkASSERT(!GrVkFormatIsCompressed(vkFormat)); 1666cb93a386Sopenharmony_ci SkASSERT(individualMipOffsets.count() == numMipLevels); 1667cb93a386Sopenharmony_ci SkASSERT(mapPtr); 1668cb93a386Sopenharmony_ci 1669cb93a386Sopenharmony_ci size_t bytesPerPixel = GrVkFormatBytesPerBlock(vkFormat); 1670cb93a386Sopenharmony_ci 1671cb93a386Sopenharmony_ci for (int level = 0; level < numMipLevels; ++level) { 1672cb93a386Sopenharmony_ci const size_t trimRB = srcData[level].info().width() * bytesPerPixel; 1673cb93a386Sopenharmony_ci 1674cb93a386Sopenharmony_ci SkRectMemcpy(mapPtr + individualMipOffsets[level], trimRB, 1675cb93a386Sopenharmony_ci srcData[level].addr(), srcData[level].rowBytes(), 1676cb93a386Sopenharmony_ci trimRB, srcData[level].height()); 1677cb93a386Sopenharmony_ci } 1678cb93a386Sopenharmony_ci return true; 1679cb93a386Sopenharmony_ci} 1680cb93a386Sopenharmony_ci 1681cb93a386Sopenharmony_cibool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat, 1682cb93a386Sopenharmony_ci SkISize dimensions, 1683cb93a386Sopenharmony_ci int sampleCnt, 1684cb93a386Sopenharmony_ci GrTexturable texturable, 1685cb93a386Sopenharmony_ci GrRenderable renderable, 1686cb93a386Sopenharmony_ci GrMipmapped mipMapped, 1687cb93a386Sopenharmony_ci GrVkImageInfo* info, 1688cb93a386Sopenharmony_ci GrProtected isProtected) { 1689cb93a386Sopenharmony_ci SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes); 1690cb93a386Sopenharmony_ci 1691cb93a386Sopenharmony_ci if (fProtectedContext != isProtected) { 1692cb93a386Sopenharmony_ci return false; 1693cb93a386Sopenharmony_ci } 1694cb93a386Sopenharmony_ci 1695cb93a386Sopenharmony_ci if (texturable == GrTexturable::kYes && !fVkCaps->isVkFormatTexturable(vkFormat)) { 1696cb93a386Sopenharmony_ci return false; 1697cb93a386Sopenharmony_ci } 1698cb93a386Sopenharmony_ci 1699cb93a386Sopenharmony_ci // MSAA images are only currently used by createTestingOnlyBackendRenderTarget. 1700cb93a386Sopenharmony_ci if (sampleCnt > 1 && (texturable == GrTexturable::kYes || renderable == GrRenderable::kNo)) { 1701cb93a386Sopenharmony_ci return false; 1702cb93a386Sopenharmony_ci } 1703cb93a386Sopenharmony_ci 1704cb93a386Sopenharmony_ci if (renderable == GrRenderable::kYes) { 1705cb93a386Sopenharmony_ci sampleCnt = fVkCaps->getRenderTargetSampleCount(sampleCnt, vkFormat); 1706cb93a386Sopenharmony_ci if (!sampleCnt) { 1707cb93a386Sopenharmony_ci return false; 1708cb93a386Sopenharmony_ci } 1709cb93a386Sopenharmony_ci } 1710cb93a386Sopenharmony_ci 1711cb93a386Sopenharmony_ci 1712cb93a386Sopenharmony_ci int numMipLevels = 1; 1713cb93a386Sopenharmony_ci if (mipMapped == GrMipmapped::kYes) { 1714cb93a386Sopenharmony_ci numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; 1715cb93a386Sopenharmony_ci } 1716cb93a386Sopenharmony_ci 1717cb93a386Sopenharmony_ci VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 1718cb93a386Sopenharmony_ci VK_IMAGE_USAGE_TRANSFER_DST_BIT; 1719cb93a386Sopenharmony_ci if (texturable == GrTexturable::kYes) { 1720cb93a386Sopenharmony_ci usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT; 1721cb93a386Sopenharmony_ci } 1722cb93a386Sopenharmony_ci if (renderable == GrRenderable::kYes) { 1723cb93a386Sopenharmony_ci usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 1724cb93a386Sopenharmony_ci // We always make our render targets support being used as input attachments 1725cb93a386Sopenharmony_ci usageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 1726cb93a386Sopenharmony_ci } 1727cb93a386Sopenharmony_ci 1728cb93a386Sopenharmony_ci GrVkImage::ImageDesc imageDesc; 1729cb93a386Sopenharmony_ci imageDesc.fImageType = VK_IMAGE_TYPE_2D; 1730cb93a386Sopenharmony_ci imageDesc.fFormat = vkFormat; 1731cb93a386Sopenharmony_ci imageDesc.fWidth = dimensions.width(); 1732cb93a386Sopenharmony_ci imageDesc.fHeight = dimensions.height(); 1733cb93a386Sopenharmony_ci imageDesc.fLevels = numMipLevels; 1734cb93a386Sopenharmony_ci imageDesc.fSamples = sampleCnt; 1735cb93a386Sopenharmony_ci imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL; 1736cb93a386Sopenharmony_ci imageDesc.fUsageFlags = usageFlags; 1737cb93a386Sopenharmony_ci imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 1738cb93a386Sopenharmony_ci imageDesc.fIsProtected = fProtectedContext; 1739cb93a386Sopenharmony_ci 1740cb93a386Sopenharmony_ci if (!GrVkImage::InitImageInfo(this, imageDesc, info)) { 1741cb93a386Sopenharmony_ci SkDebugf("Failed to init image info\n"); 1742cb93a386Sopenharmony_ci return false; 1743cb93a386Sopenharmony_ci } 1744cb93a386Sopenharmony_ci 1745cb93a386Sopenharmony_ci return true; 1746cb93a386Sopenharmony_ci} 1747cb93a386Sopenharmony_ci 1748cb93a386Sopenharmony_cibool GrVkGpu::onClearBackendTexture(const GrBackendTexture& backendTexture, 1749cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> finishedCallback, 1750cb93a386Sopenharmony_ci std::array<float, 4> color) { 1751cb93a386Sopenharmony_ci GrVkImageInfo info; 1752cb93a386Sopenharmony_ci SkAssertResult(backendTexture.getVkImageInfo(&info)); 1753cb93a386Sopenharmony_ci 1754cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTexture.getMutableState(); 1755cb93a386Sopenharmony_ci SkASSERT(mutableState); 1756cb93a386Sopenharmony_ci sk_sp<GrVkTexture> texture = 1757cb93a386Sopenharmony_ci GrVkTexture::MakeWrappedTexture(this, backendTexture.dimensions(), 1758cb93a386Sopenharmony_ci kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, 1759cb93a386Sopenharmony_ci kRW_GrIOType, info, std::move(mutableState)); 1760cb93a386Sopenharmony_ci if (!texture) { 1761cb93a386Sopenharmony_ci return false; 1762cb93a386Sopenharmony_ci } 1763cb93a386Sopenharmony_ci GrVkImage* texImage = texture->textureImage(); 1764cb93a386Sopenharmony_ci 1765cb93a386Sopenharmony_ci GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer(); 1766cb93a386Sopenharmony_ci if (!cmdBuffer) { 1767cb93a386Sopenharmony_ci return false; 1768cb93a386Sopenharmony_ci } 1769cb93a386Sopenharmony_ci 1770cb93a386Sopenharmony_ci texImage->setImageLayout(this, 1771cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1772cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 1773cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 1774cb93a386Sopenharmony_ci false); 1775cb93a386Sopenharmony_ci 1776cb93a386Sopenharmony_ci // CmdClearColorImage doesn't work for compressed formats 1777cb93a386Sopenharmony_ci SkASSERT(!GrVkFormatIsCompressed(info.fFormat)); 1778cb93a386Sopenharmony_ci 1779cb93a386Sopenharmony_ci VkClearColorValue vkColor; 1780cb93a386Sopenharmony_ci // If we ever support SINT or UINT formats this needs to be updated to use the int32 and 1781cb93a386Sopenharmony_ci // uint32 union members in those cases. 1782cb93a386Sopenharmony_ci vkColor.float32[0] = color[0]; 1783cb93a386Sopenharmony_ci vkColor.float32[1] = color[1]; 1784cb93a386Sopenharmony_ci vkColor.float32[2] = color[2]; 1785cb93a386Sopenharmony_ci vkColor.float32[3] = color[3]; 1786cb93a386Sopenharmony_ci VkImageSubresourceRange range; 1787cb93a386Sopenharmony_ci range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1788cb93a386Sopenharmony_ci range.baseArrayLayer = 0; 1789cb93a386Sopenharmony_ci range.baseMipLevel = 0; 1790cb93a386Sopenharmony_ci range.layerCount = 1; 1791cb93a386Sopenharmony_ci range.levelCount = info.fLevelCount; 1792cb93a386Sopenharmony_ci cmdBuffer->clearColorImage(this, texImage, &vkColor, 1, &range); 1793cb93a386Sopenharmony_ci 1794cb93a386Sopenharmony_ci // Change image layout to shader read since if we use this texture as a borrowed 1795cb93a386Sopenharmony_ci // texture within Ganesh we require that its layout be set to that 1796cb93a386Sopenharmony_ci texImage->setImageLayout(this, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1797cb93a386Sopenharmony_ci VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 1798cb93a386Sopenharmony_ci false); 1799cb93a386Sopenharmony_ci 1800cb93a386Sopenharmony_ci if (finishedCallback) { 1801cb93a386Sopenharmony_ci this->addFinishedCallback(std::move(finishedCallback)); 1802cb93a386Sopenharmony_ci } 1803cb93a386Sopenharmony_ci return true; 1804cb93a386Sopenharmony_ci} 1805cb93a386Sopenharmony_ci 1806cb93a386Sopenharmony_ciGrBackendTexture GrVkGpu::onCreateBackendTexture(SkISize dimensions, 1807cb93a386Sopenharmony_ci const GrBackendFormat& format, 1808cb93a386Sopenharmony_ci GrRenderable renderable, 1809cb93a386Sopenharmony_ci GrMipmapped mipMapped, 1810cb93a386Sopenharmony_ci GrProtected isProtected) { 1811cb93a386Sopenharmony_ci const GrVkCaps& caps = this->vkCaps(); 1812cb93a386Sopenharmony_ci 1813cb93a386Sopenharmony_ci if (fProtectedContext != isProtected) { 1814cb93a386Sopenharmony_ci return {}; 1815cb93a386Sopenharmony_ci } 1816cb93a386Sopenharmony_ci 1817cb93a386Sopenharmony_ci VkFormat vkFormat; 1818cb93a386Sopenharmony_ci if (!format.asVkFormat(&vkFormat)) { 1819cb93a386Sopenharmony_ci return {}; 1820cb93a386Sopenharmony_ci } 1821cb93a386Sopenharmony_ci 1822cb93a386Sopenharmony_ci // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here 1823cb93a386Sopenharmony_ci if (!caps.isVkFormatTexturable(vkFormat)) { 1824cb93a386Sopenharmony_ci return {}; 1825cb93a386Sopenharmony_ci } 1826cb93a386Sopenharmony_ci 1827cb93a386Sopenharmony_ci if (GrVkFormatNeedsYcbcrSampler(vkFormat)) { 1828cb93a386Sopenharmony_ci return {}; 1829cb93a386Sopenharmony_ci } 1830cb93a386Sopenharmony_ci 1831cb93a386Sopenharmony_ci GrVkImageInfo info; 1832cb93a386Sopenharmony_ci if (!this->createVkImageForBackendSurface(vkFormat, dimensions, 1, GrTexturable::kYes, 1833cb93a386Sopenharmony_ci renderable, mipMapped, &info, isProtected)) { 1834cb93a386Sopenharmony_ci return {}; 1835cb93a386Sopenharmony_ci } 1836cb93a386Sopenharmony_ci 1837cb93a386Sopenharmony_ci return GrBackendTexture(dimensions.width(), dimensions.height(), info); 1838cb93a386Sopenharmony_ci} 1839cb93a386Sopenharmony_ci 1840cb93a386Sopenharmony_ciGrBackendTexture GrVkGpu::onCreateCompressedBackendTexture( 1841cb93a386Sopenharmony_ci SkISize dimensions, const GrBackendFormat& format, GrMipmapped mipMapped, 1842cb93a386Sopenharmony_ci GrProtected isProtected) { 1843cb93a386Sopenharmony_ci return this->onCreateBackendTexture(dimensions, format, GrRenderable::kNo, mipMapped, 1844cb93a386Sopenharmony_ci isProtected); 1845cb93a386Sopenharmony_ci} 1846cb93a386Sopenharmony_ci 1847cb93a386Sopenharmony_cibool GrVkGpu::onUpdateCompressedBackendTexture(const GrBackendTexture& backendTexture, 1848cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> finishedCallback, 1849cb93a386Sopenharmony_ci const void* data, 1850cb93a386Sopenharmony_ci size_t size) { 1851cb93a386Sopenharmony_ci GrVkImageInfo info; 1852cb93a386Sopenharmony_ci SkAssertResult(backendTexture.getVkImageInfo(&info)); 1853cb93a386Sopenharmony_ci 1854cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTexture.getMutableState(); 1855cb93a386Sopenharmony_ci SkASSERT(mutableState); 1856cb93a386Sopenharmony_ci sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture(this, 1857cb93a386Sopenharmony_ci backendTexture.dimensions(), 1858cb93a386Sopenharmony_ci kBorrow_GrWrapOwnership, 1859cb93a386Sopenharmony_ci GrWrapCacheable::kNo, 1860cb93a386Sopenharmony_ci kRW_GrIOType, 1861cb93a386Sopenharmony_ci info, 1862cb93a386Sopenharmony_ci std::move(mutableState)); 1863cb93a386Sopenharmony_ci if (!texture) { 1864cb93a386Sopenharmony_ci return false; 1865cb93a386Sopenharmony_ci } 1866cb93a386Sopenharmony_ci 1867cb93a386Sopenharmony_ci GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer(); 1868cb93a386Sopenharmony_ci if (!cmdBuffer) { 1869cb93a386Sopenharmony_ci return false; 1870cb93a386Sopenharmony_ci } 1871cb93a386Sopenharmony_ci GrVkImage* image = texture->textureImage(); 1872cb93a386Sopenharmony_ci image->setImageLayout(this, 1873cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1874cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 1875cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 1876cb93a386Sopenharmony_ci false); 1877cb93a386Sopenharmony_ci 1878cb93a386Sopenharmony_ci SkImage::CompressionType compression = 1879cb93a386Sopenharmony_ci GrBackendFormatToCompressionType(backendTexture.getBackendFormat()); 1880cb93a386Sopenharmony_ci 1881cb93a386Sopenharmony_ci SkTArray<VkBufferImageCopy> regions; 1882cb93a386Sopenharmony_ci SkTArray<size_t> individualMipOffsets; 1883cb93a386Sopenharmony_ci GrStagingBufferManager::Slice slice; 1884cb93a386Sopenharmony_ci 1885cb93a386Sopenharmony_ci fill_in_compressed_regions(&fStagingBufferManager, 1886cb93a386Sopenharmony_ci ®ions, 1887cb93a386Sopenharmony_ci &individualMipOffsets, 1888cb93a386Sopenharmony_ci &slice, 1889cb93a386Sopenharmony_ci compression, 1890cb93a386Sopenharmony_ci info.fFormat, 1891cb93a386Sopenharmony_ci backendTexture.dimensions(), 1892cb93a386Sopenharmony_ci backendTexture.fMipmapped); 1893cb93a386Sopenharmony_ci 1894cb93a386Sopenharmony_ci if (!slice.fBuffer) { 1895cb93a386Sopenharmony_ci return false; 1896cb93a386Sopenharmony_ci } 1897cb93a386Sopenharmony_ci 1898cb93a386Sopenharmony_ci memcpy(slice.fOffsetMapPtr, data, size); 1899cb93a386Sopenharmony_ci 1900cb93a386Sopenharmony_ci cmdBuffer->addGrSurface(texture); 1901cb93a386Sopenharmony_ci // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer 1902cb93a386Sopenharmony_ci // because we don't need the command buffer to ref the buffer here. The reason being is that 1903cb93a386Sopenharmony_ci // the buffer is coming from the staging manager and the staging manager will make sure the 1904cb93a386Sopenharmony_ci // command buffer has a ref on the buffer. This avoids having to add and remove a ref for 1905cb93a386Sopenharmony_ci // every upload in the frame. 1906cb93a386Sopenharmony_ci cmdBuffer->copyBufferToImage(this, 1907cb93a386Sopenharmony_ci static_cast<GrVkBuffer*>(slice.fBuffer)->vkBuffer(), 1908cb93a386Sopenharmony_ci image, 1909cb93a386Sopenharmony_ci image->currentLayout(), 1910cb93a386Sopenharmony_ci regions.count(), 1911cb93a386Sopenharmony_ci regions.begin()); 1912cb93a386Sopenharmony_ci 1913cb93a386Sopenharmony_ci // Change image layout to shader read since if we use this texture as a borrowed 1914cb93a386Sopenharmony_ci // texture within Ganesh we require that its layout be set to that 1915cb93a386Sopenharmony_ci image->setImageLayout(this, 1916cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1917cb93a386Sopenharmony_ci VK_ACCESS_SHADER_READ_BIT, 1918cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 1919cb93a386Sopenharmony_ci false); 1920cb93a386Sopenharmony_ci 1921cb93a386Sopenharmony_ci if (finishedCallback) { 1922cb93a386Sopenharmony_ci this->addFinishedCallback(std::move(finishedCallback)); 1923cb93a386Sopenharmony_ci } 1924cb93a386Sopenharmony_ci return true; 1925cb93a386Sopenharmony_ci} 1926cb93a386Sopenharmony_ci 1927cb93a386Sopenharmony_civoid set_layout_and_queue_from_mutable_state(GrVkGpu* gpu, GrVkImage* image, 1928cb93a386Sopenharmony_ci const GrVkSharedImageInfo& newInfo) { 1929cb93a386Sopenharmony_ci // Even though internally we use this helper for getting src access flags and stages they 1930cb93a386Sopenharmony_ci // can also be used for general dst flags since we don't know exactly what the client 1931cb93a386Sopenharmony_ci // plans on using the image for. 1932cb93a386Sopenharmony_ci VkImageLayout newLayout = newInfo.getImageLayout(); 1933cb93a386Sopenharmony_ci if (newLayout == VK_IMAGE_LAYOUT_UNDEFINED) { 1934cb93a386Sopenharmony_ci newLayout = image->currentLayout(); 1935cb93a386Sopenharmony_ci } 1936cb93a386Sopenharmony_ci VkPipelineStageFlags dstStage = GrVkImage::LayoutToPipelineSrcStageFlags(newLayout); 1937cb93a386Sopenharmony_ci VkAccessFlags dstAccess = GrVkImage::LayoutToSrcAccessMask(newLayout); 1938cb93a386Sopenharmony_ci 1939cb93a386Sopenharmony_ci uint32_t currentQueueFamilyIndex = image->currentQueueFamilyIndex(); 1940cb93a386Sopenharmony_ci uint32_t newQueueFamilyIndex = newInfo.getQueueFamilyIndex(); 1941cb93a386Sopenharmony_ci auto isSpecialQueue = [](uint32_t queueFamilyIndex) { 1942cb93a386Sopenharmony_ci return queueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL || 1943cb93a386Sopenharmony_ci queueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT; 1944cb93a386Sopenharmony_ci }; 1945cb93a386Sopenharmony_ci if (isSpecialQueue(currentQueueFamilyIndex) && isSpecialQueue(newQueueFamilyIndex)) { 1946cb93a386Sopenharmony_ci // It is illegal to have both the new and old queue be special queue families (i.e. external 1947cb93a386Sopenharmony_ci // or foreign). 1948cb93a386Sopenharmony_ci return; 1949cb93a386Sopenharmony_ci } 1950cb93a386Sopenharmony_ci 1951cb93a386Sopenharmony_ci image->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccess, dstStage, false, 1952cb93a386Sopenharmony_ci newQueueFamilyIndex); 1953cb93a386Sopenharmony_ci} 1954cb93a386Sopenharmony_ci 1955cb93a386Sopenharmony_cibool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info, 1956cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> currentState, 1957cb93a386Sopenharmony_ci SkISize dimensions, 1958cb93a386Sopenharmony_ci const GrVkSharedImageInfo& newInfo, 1959cb93a386Sopenharmony_ci GrBackendSurfaceMutableState* previousState, 1960cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> finishedCallback) { 1961cb93a386Sopenharmony_ci sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(this, 1962cb93a386Sopenharmony_ci dimensions, 1963cb93a386Sopenharmony_ci info, 1964cb93a386Sopenharmony_ci std::move(currentState), 1965cb93a386Sopenharmony_ci GrVkImage::UsageFlags::kColorAttachment, 1966cb93a386Sopenharmony_ci kBorrow_GrWrapOwnership, 1967cb93a386Sopenharmony_ci GrWrapCacheable::kNo, 1968cb93a386Sopenharmony_ci /*forSecondaryCB=*/false); 1969cb93a386Sopenharmony_ci SkASSERT(texture); 1970cb93a386Sopenharmony_ci if (!texture) { 1971cb93a386Sopenharmony_ci return false; 1972cb93a386Sopenharmony_ci } 1973cb93a386Sopenharmony_ci if (previousState) { 1974cb93a386Sopenharmony_ci previousState->setVulkanState(texture->currentLayout(), 1975cb93a386Sopenharmony_ci texture->currentQueueFamilyIndex()); 1976cb93a386Sopenharmony_ci } 1977cb93a386Sopenharmony_ci set_layout_and_queue_from_mutable_state(this, texture.get(), newInfo); 1978cb93a386Sopenharmony_ci if (finishedCallback) { 1979cb93a386Sopenharmony_ci this->addFinishedCallback(std::move(finishedCallback)); 1980cb93a386Sopenharmony_ci } 1981cb93a386Sopenharmony_ci return true; 1982cb93a386Sopenharmony_ci} 1983cb93a386Sopenharmony_ci 1984cb93a386Sopenharmony_cibool GrVkGpu::setBackendTextureState(const GrBackendTexture& backendTeture, 1985cb93a386Sopenharmony_ci const GrBackendSurfaceMutableState& newState, 1986cb93a386Sopenharmony_ci GrBackendSurfaceMutableState* previousState, 1987cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> finishedCallback) { 1988cb93a386Sopenharmony_ci GrVkImageInfo info; 1989cb93a386Sopenharmony_ci SkAssertResult(backendTeture.getVkImageInfo(&info)); 1990cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendTeture.getMutableState(); 1991cb93a386Sopenharmony_ci SkASSERT(currentState); 1992cb93a386Sopenharmony_ci SkASSERT(newState.isValid() && newState.fBackend == GrBackend::kVulkan); 1993cb93a386Sopenharmony_ci return this->setBackendSurfaceState(info, std::move(currentState), backendTeture.dimensions(), 1994cb93a386Sopenharmony_ci newState.fVkState, previousState, 1995cb93a386Sopenharmony_ci std::move(finishedCallback)); 1996cb93a386Sopenharmony_ci} 1997cb93a386Sopenharmony_ci 1998cb93a386Sopenharmony_cibool GrVkGpu::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget, 1999cb93a386Sopenharmony_ci const GrBackendSurfaceMutableState& newState, 2000cb93a386Sopenharmony_ci GrBackendSurfaceMutableState* previousState, 2001cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> finishedCallback) { 2002cb93a386Sopenharmony_ci GrVkImageInfo info; 2003cb93a386Sopenharmony_ci SkAssertResult(backendRenderTarget.getVkImageInfo(&info)); 2004cb93a386Sopenharmony_ci sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendRenderTarget.getMutableState(); 2005cb93a386Sopenharmony_ci SkASSERT(currentState); 2006cb93a386Sopenharmony_ci SkASSERT(newState.fBackend == GrBackend::kVulkan); 2007cb93a386Sopenharmony_ci return this->setBackendSurfaceState(info, std::move(currentState), 2008cb93a386Sopenharmony_ci backendRenderTarget.dimensions(), newState.fVkState, 2009cb93a386Sopenharmony_ci previousState, std::move(finishedCallback)); 2010cb93a386Sopenharmony_ci} 2011cb93a386Sopenharmony_ci 2012cb93a386Sopenharmony_civoid GrVkGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType barrierType) { 2013cb93a386Sopenharmony_ci GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); 2014cb93a386Sopenharmony_ci VkPipelineStageFlags dstStage; 2015cb93a386Sopenharmony_ci VkAccessFlags dstAccess; 2016cb93a386Sopenharmony_ci if (barrierType == kBlend_GrXferBarrierType) { 2017cb93a386Sopenharmony_ci dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 2018cb93a386Sopenharmony_ci dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT; 2019cb93a386Sopenharmony_ci } else { 2020cb93a386Sopenharmony_ci SkASSERT(barrierType == kTexture_GrXferBarrierType); 2021cb93a386Sopenharmony_ci dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 2022cb93a386Sopenharmony_ci dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 2023cb93a386Sopenharmony_ci } 2024cb93a386Sopenharmony_ci GrVkImage* image = vkRT->colorAttachment(); 2025cb93a386Sopenharmony_ci VkImageMemoryBarrier barrier; 2026cb93a386Sopenharmony_ci barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 2027cb93a386Sopenharmony_ci barrier.pNext = nullptr; 2028cb93a386Sopenharmony_ci barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 2029cb93a386Sopenharmony_ci barrier.dstAccessMask = dstAccess; 2030cb93a386Sopenharmony_ci barrier.oldLayout = image->currentLayout(); 2031cb93a386Sopenharmony_ci barrier.newLayout = barrier.oldLayout; 2032cb93a386Sopenharmony_ci barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 2033cb93a386Sopenharmony_ci barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 2034cb93a386Sopenharmony_ci barrier.image = image->image(); 2035cb93a386Sopenharmony_ci barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, image->mipLevels(), 0, 1}; 2036cb93a386Sopenharmony_ci this->addImageMemoryBarrier(image->resource(), 2037cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 2038cb93a386Sopenharmony_ci dstStage, true, &barrier); 2039cb93a386Sopenharmony_ci} 2040cb93a386Sopenharmony_ci 2041cb93a386Sopenharmony_civoid GrVkGpu::deleteBackendTexture(const GrBackendTexture& tex) { 2042cb93a386Sopenharmony_ci SkASSERT(GrBackendApi::kVulkan == tex.fBackend); 2043cb93a386Sopenharmony_ci 2044cb93a386Sopenharmony_ci GrVkImageInfo info; 2045cb93a386Sopenharmony_ci if (tex.getVkImageInfo(&info)) { 2046cb93a386Sopenharmony_ci GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(&info)); 2047cb93a386Sopenharmony_ci } 2048cb93a386Sopenharmony_ci} 2049cb93a386Sopenharmony_ci 2050cb93a386Sopenharmony_cibool GrVkGpu::compile(const GrProgramDesc& desc, const GrProgramInfo& programInfo) { 2051cb93a386Sopenharmony_ci GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor; 2052cb93a386Sopenharmony_ci GrVkRenderPass::AttachmentFlags attachmentFlags; 2053cb93a386Sopenharmony_ci GrVkRenderTarget::ReconstructAttachmentsDescriptor(this->vkCaps(), programInfo, 2054cb93a386Sopenharmony_ci &attachmentsDescriptor, &attachmentFlags); 2055cb93a386Sopenharmony_ci 2056cb93a386Sopenharmony_ci GrVkRenderPass::SelfDependencyFlags selfDepFlags = GrVkRenderPass::SelfDependencyFlags::kNone; 2057cb93a386Sopenharmony_ci if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kBlend) { 2058cb93a386Sopenharmony_ci selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend; 2059cb93a386Sopenharmony_ci } 2060cb93a386Sopenharmony_ci if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kTexture) { 2061cb93a386Sopenharmony_ci selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForInputAttachment; 2062cb93a386Sopenharmony_ci } 2063cb93a386Sopenharmony_ci 2064cb93a386Sopenharmony_ci GrVkRenderPass::LoadFromResolve loadFromResolve = GrVkRenderPass::LoadFromResolve::kNo; 2065cb93a386Sopenharmony_ci if (this->vkCaps().programInfoWillUseDiscardableMSAA(programInfo) && 2066cb93a386Sopenharmony_ci programInfo.colorLoadOp() == GrLoadOp::kLoad) { 2067cb93a386Sopenharmony_ci loadFromResolve = GrVkRenderPass::LoadFromResolve::kLoad; 2068cb93a386Sopenharmony_ci } 2069cb93a386Sopenharmony_ci sk_sp<const GrVkRenderPass> renderPass(this->resourceProvider().findCompatibleRenderPass( 2070cb93a386Sopenharmony_ci &attachmentsDescriptor, attachmentFlags, selfDepFlags, loadFromResolve)); 2071cb93a386Sopenharmony_ci if (!renderPass) { 2072cb93a386Sopenharmony_ci return false; 2073cb93a386Sopenharmony_ci } 2074cb93a386Sopenharmony_ci 2075cb93a386Sopenharmony_ci GrThreadSafePipelineBuilder::Stats::ProgramCacheResult stat; 2076cb93a386Sopenharmony_ci 2077cb93a386Sopenharmony_ci auto pipelineState = this->resourceProvider().findOrCreateCompatiblePipelineState( 2078cb93a386Sopenharmony_ci desc, 2079cb93a386Sopenharmony_ci programInfo, 2080cb93a386Sopenharmony_ci renderPass->vkRenderPass(), 2081cb93a386Sopenharmony_ci &stat); 2082cb93a386Sopenharmony_ci if (!pipelineState) { 2083cb93a386Sopenharmony_ci return false; 2084cb93a386Sopenharmony_ci } 2085cb93a386Sopenharmony_ci 2086cb93a386Sopenharmony_ci return stat != GrThreadSafePipelineBuilder::Stats::ProgramCacheResult::kHit; 2087cb93a386Sopenharmony_ci} 2088cb93a386Sopenharmony_ci 2089cb93a386Sopenharmony_ci#if GR_TEST_UTILS 2090cb93a386Sopenharmony_cibool GrVkGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const { 2091cb93a386Sopenharmony_ci SkASSERT(GrBackendApi::kVulkan == tex.fBackend); 2092cb93a386Sopenharmony_ci 2093cb93a386Sopenharmony_ci GrVkImageInfo backend; 2094cb93a386Sopenharmony_ci if (!tex.getVkImageInfo(&backend)) { 2095cb93a386Sopenharmony_ci return false; 2096cb93a386Sopenharmony_ci } 2097cb93a386Sopenharmony_ci 2098cb93a386Sopenharmony_ci if (backend.fImage && backend.fAlloc.fMemory) { 2099cb93a386Sopenharmony_ci VkMemoryRequirements req; 2100cb93a386Sopenharmony_ci memset(&req, 0, sizeof(req)); 2101cb93a386Sopenharmony_ci GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice, 2102cb93a386Sopenharmony_ci backend.fImage, 2103cb93a386Sopenharmony_ci &req)); 2104cb93a386Sopenharmony_ci // TODO: find a better check 2105cb93a386Sopenharmony_ci // This will probably fail with a different driver 2106cb93a386Sopenharmony_ci return (req.size > 0) && (req.size <= 8192 * 8192); 2107cb93a386Sopenharmony_ci } 2108cb93a386Sopenharmony_ci 2109cb93a386Sopenharmony_ci return false; 2110cb93a386Sopenharmony_ci} 2111cb93a386Sopenharmony_ci 2112cb93a386Sopenharmony_ciGrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions, 2113cb93a386Sopenharmony_ci GrColorType ct, 2114cb93a386Sopenharmony_ci int sampleCnt, 2115cb93a386Sopenharmony_ci GrProtected isProtected) { 2116cb93a386Sopenharmony_ci if (dimensions.width() > this->caps()->maxRenderTargetSize() || 2117cb93a386Sopenharmony_ci dimensions.height() > this->caps()->maxRenderTargetSize()) { 2118cb93a386Sopenharmony_ci return {}; 2119cb93a386Sopenharmony_ci } 2120cb93a386Sopenharmony_ci 2121cb93a386Sopenharmony_ci VkFormat vkFormat = this->vkCaps().getFormatFromColorType(ct); 2122cb93a386Sopenharmony_ci 2123cb93a386Sopenharmony_ci GrVkImageInfo info; 2124cb93a386Sopenharmony_ci if (!this->createVkImageForBackendSurface(vkFormat, dimensions, sampleCnt, GrTexturable::kNo, 2125cb93a386Sopenharmony_ci GrRenderable::kYes, GrMipmapped::kNo, &info, 2126cb93a386Sopenharmony_ci isProtected)) { 2127cb93a386Sopenharmony_ci return {}; 2128cb93a386Sopenharmony_ci } 2129cb93a386Sopenharmony_ci return GrBackendRenderTarget(dimensions.width(), dimensions.height(), 0, info); 2130cb93a386Sopenharmony_ci} 2131cb93a386Sopenharmony_ci 2132cb93a386Sopenharmony_civoid GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) { 2133cb93a386Sopenharmony_ci SkASSERT(GrBackendApi::kVulkan == rt.fBackend); 2134cb93a386Sopenharmony_ci 2135cb93a386Sopenharmony_ci GrVkImageInfo info; 2136cb93a386Sopenharmony_ci if (rt.getVkImageInfo(&info)) { 2137cb93a386Sopenharmony_ci // something in the command buffer may still be using this, so force submit 2138cb93a386Sopenharmony_ci SkAssertResult(this->submitCommandBuffer(kForce_SyncQueue)); 2139cb93a386Sopenharmony_ci GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(&info)); 2140cb93a386Sopenharmony_ci } 2141cb93a386Sopenharmony_ci} 2142cb93a386Sopenharmony_ci#endif 2143cb93a386Sopenharmony_ci 2144cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 2145cb93a386Sopenharmony_ci 2146cb93a386Sopenharmony_civoid GrVkGpu::addBufferMemoryBarrier(const GrManagedResource* resource, 2147cb93a386Sopenharmony_ci VkPipelineStageFlags srcStageMask, 2148cb93a386Sopenharmony_ci VkPipelineStageFlags dstStageMask, 2149cb93a386Sopenharmony_ci bool byRegion, 2150cb93a386Sopenharmony_ci VkBufferMemoryBarrier* barrier) const { 2151cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2152cb93a386Sopenharmony_ci return; 2153cb93a386Sopenharmony_ci } 2154cb93a386Sopenharmony_ci SkASSERT(resource); 2155cb93a386Sopenharmony_ci this->currentCommandBuffer()->pipelineBarrier(this, 2156cb93a386Sopenharmony_ci resource, 2157cb93a386Sopenharmony_ci srcStageMask, 2158cb93a386Sopenharmony_ci dstStageMask, 2159cb93a386Sopenharmony_ci byRegion, 2160cb93a386Sopenharmony_ci GrVkCommandBuffer::kBufferMemory_BarrierType, 2161cb93a386Sopenharmony_ci barrier); 2162cb93a386Sopenharmony_ci} 2163cb93a386Sopenharmony_civoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask, 2164cb93a386Sopenharmony_ci VkPipelineStageFlags dstStageMask, 2165cb93a386Sopenharmony_ci bool byRegion, 2166cb93a386Sopenharmony_ci VkBufferMemoryBarrier* barrier) const { 2167cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2168cb93a386Sopenharmony_ci return; 2169cb93a386Sopenharmony_ci } 2170cb93a386Sopenharmony_ci // We don't pass in a resource here to the command buffer. The command buffer only is using it 2171cb93a386Sopenharmony_ci // to hold a ref, but every place where we add a buffer memory barrier we are doing some other 2172cb93a386Sopenharmony_ci // command with the buffer on the command buffer. Thus those other commands will already cause 2173cb93a386Sopenharmony_ci // the command buffer to be holding a ref to the buffer. 2174cb93a386Sopenharmony_ci this->currentCommandBuffer()->pipelineBarrier(this, 2175cb93a386Sopenharmony_ci /*resource=*/nullptr, 2176cb93a386Sopenharmony_ci srcStageMask, 2177cb93a386Sopenharmony_ci dstStageMask, 2178cb93a386Sopenharmony_ci byRegion, 2179cb93a386Sopenharmony_ci GrVkCommandBuffer::kBufferMemory_BarrierType, 2180cb93a386Sopenharmony_ci barrier); 2181cb93a386Sopenharmony_ci} 2182cb93a386Sopenharmony_ci 2183cb93a386Sopenharmony_civoid GrVkGpu::addImageMemoryBarrier(const GrManagedResource* resource, 2184cb93a386Sopenharmony_ci VkPipelineStageFlags srcStageMask, 2185cb93a386Sopenharmony_ci VkPipelineStageFlags dstStageMask, 2186cb93a386Sopenharmony_ci bool byRegion, 2187cb93a386Sopenharmony_ci VkImageMemoryBarrier* barrier) const { 2188cb93a386Sopenharmony_ci // If we are in the middle of destroying or abandoning the context we may hit a release proc 2189cb93a386Sopenharmony_ci // that triggers the destruction of a GrVkImage. This could cause us to try and transfer the 2190cb93a386Sopenharmony_ci // VkImage back to the original queue. In this state we don't submit anymore work and we may not 2191cb93a386Sopenharmony_ci // have a current command buffer. Thus we won't do the queue transfer. 2192cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2193cb93a386Sopenharmony_ci return; 2194cb93a386Sopenharmony_ci } 2195cb93a386Sopenharmony_ci SkASSERT(resource); 2196cb93a386Sopenharmony_ci this->currentCommandBuffer()->pipelineBarrier(this, 2197cb93a386Sopenharmony_ci resource, 2198cb93a386Sopenharmony_ci srcStageMask, 2199cb93a386Sopenharmony_ci dstStageMask, 2200cb93a386Sopenharmony_ci byRegion, 2201cb93a386Sopenharmony_ci GrVkCommandBuffer::kImageMemory_BarrierType, 2202cb93a386Sopenharmony_ci barrier); 2203cb93a386Sopenharmony_ci} 2204cb93a386Sopenharmony_ci 2205cb93a386Sopenharmony_civoid GrVkGpu::prepareSurfacesForBackendAccessAndStateUpdates( 2206cb93a386Sopenharmony_ci SkSpan<GrSurfaceProxy*> proxies, 2207cb93a386Sopenharmony_ci SkSurface::BackendSurfaceAccess access, 2208cb93a386Sopenharmony_ci const GrBackendSurfaceMutableState* newState) { 2209cb93a386Sopenharmony_ci // Submit the current command buffer to the Queue. Whether we inserted semaphores or not does 2210cb93a386Sopenharmony_ci // not effect what we do here. 2211cb93a386Sopenharmony_ci if (!proxies.empty() && (access == SkSurface::BackendSurfaceAccess::kPresent || newState)) { 2212cb93a386Sopenharmony_ci // We currently don't support passing in new surface state for multiple proxies here. The 2213cb93a386Sopenharmony_ci // only time we have multiple proxies is if we are flushing a yuv SkImage which won't have 2214cb93a386Sopenharmony_ci // state updates anyways. Additionally if we have a newState than we must not have any 2215cb93a386Sopenharmony_ci // BackendSurfaceAccess. 2216cb93a386Sopenharmony_ci SkASSERT(!newState || proxies.size() == 1); 2217cb93a386Sopenharmony_ci SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess); 2218cb93a386Sopenharmony_ci GrVkImage* image; 2219cb93a386Sopenharmony_ci for (GrSurfaceProxy* proxy : proxies) { 2220cb93a386Sopenharmony_ci SkASSERT(proxy->isInstantiated()); 2221cb93a386Sopenharmony_ci if (GrTexture* tex = proxy->peekTexture()) { 2222cb93a386Sopenharmony_ci image = static_cast<GrVkTexture*>(tex)->textureImage(); 2223cb93a386Sopenharmony_ci } else { 2224cb93a386Sopenharmony_ci GrRenderTarget* rt = proxy->peekRenderTarget(); 2225cb93a386Sopenharmony_ci SkASSERT(rt); 2226cb93a386Sopenharmony_ci GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); 2227cb93a386Sopenharmony_ci image = vkRT->externalAttachment(); 2228cb93a386Sopenharmony_ci } 2229cb93a386Sopenharmony_ci if (newState) { 2230cb93a386Sopenharmony_ci const GrVkSharedImageInfo& newInfo = newState->fVkState; 2231cb93a386Sopenharmony_ci set_layout_and_queue_from_mutable_state(this, image, newInfo); 2232cb93a386Sopenharmony_ci } else { 2233cb93a386Sopenharmony_ci SkASSERT(access == SkSurface::BackendSurfaceAccess::kPresent); 2234cb93a386Sopenharmony_ci image->prepareForPresent(this); 2235cb93a386Sopenharmony_ci } 2236cb93a386Sopenharmony_ci } 2237cb93a386Sopenharmony_ci } 2238cb93a386Sopenharmony_ci} 2239cb93a386Sopenharmony_ci 2240cb93a386Sopenharmony_civoid GrVkGpu::addFinishedProc(GrGpuFinishedProc finishedProc, 2241cb93a386Sopenharmony_ci GrGpuFinishedContext finishedContext) { 2242cb93a386Sopenharmony_ci SkASSERT(finishedProc); 2243cb93a386Sopenharmony_ci this->addFinishedCallback(GrRefCntedCallback::Make(finishedProc, finishedContext)); 2244cb93a386Sopenharmony_ci} 2245cb93a386Sopenharmony_ci 2246cb93a386Sopenharmony_civoid GrVkGpu::addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback) { 2247cb93a386Sopenharmony_ci SkASSERT(finishedCallback); 2248cb93a386Sopenharmony_ci fResourceProvider.addFinishedProcToActiveCommandBuffers(std::move(finishedCallback)); 2249cb93a386Sopenharmony_ci} 2250cb93a386Sopenharmony_ci 2251cb93a386Sopenharmony_civoid GrVkGpu::takeOwnershipOfBuffer(sk_sp<GrGpuBuffer> buffer) { 2252cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrBuffer(std::move(buffer)); 2253cb93a386Sopenharmony_ci} 2254cb93a386Sopenharmony_ci 2255cb93a386Sopenharmony_cibool GrVkGpu::onSubmitToGpu(bool syncCpu) { 2256cb93a386Sopenharmony_ci if (syncCpu) { 2257cb93a386Sopenharmony_ci return this->submitCommandBuffer(kForce_SyncQueue); 2258cb93a386Sopenharmony_ci } else { 2259cb93a386Sopenharmony_ci return this->submitCommandBuffer(kSkip_SyncQueue); 2260cb93a386Sopenharmony_ci } 2261cb93a386Sopenharmony_ci} 2262cb93a386Sopenharmony_ci 2263cb93a386Sopenharmony_civoid GrVkGpu::finishOutstandingGpuWork() { 2264cb93a386Sopenharmony_ci VK_CALL(QueueWaitIdle(fQueue)); 2265cb93a386Sopenharmony_ci 2266cb93a386Sopenharmony_ci if (this->vkCaps().mustSyncCommandBuffersWithQueue()) { 2267cb93a386Sopenharmony_ci fResourceProvider.forceSyncAllCommandBuffers(); 2268cb93a386Sopenharmony_ci } 2269cb93a386Sopenharmony_ci} 2270cb93a386Sopenharmony_ci 2271cb93a386Sopenharmony_civoid GrVkGpu::onReportSubmitHistograms() { 2272cb93a386Sopenharmony_ci#if SK_HISTOGRAMS_ENABLED 2273cb93a386Sopenharmony_ci uint64_t allocatedMemory = fMemoryAllocator->totalAllocatedMemory(); 2274cb93a386Sopenharmony_ci uint64_t usedMemory = fMemoryAllocator->totalUsedMemory(); 2275cb93a386Sopenharmony_ci SkASSERT(usedMemory <= allocatedMemory); 2276cb93a386Sopenharmony_ci if (allocatedMemory > 0) { 2277cb93a386Sopenharmony_ci SK_HISTOGRAM_PERCENTAGE("VulkanMemoryAllocator.PercentUsed", 2278cb93a386Sopenharmony_ci (usedMemory * 100) / allocatedMemory); 2279cb93a386Sopenharmony_ci } 2280cb93a386Sopenharmony_ci // allocatedMemory is in bytes and need to be reported it in kilobytes. SK_HISTOGRAM_MEMORY_KB 2281cb93a386Sopenharmony_ci // supports samples up to around 500MB which should support the amounts of memory we allocate. 2282cb93a386Sopenharmony_ci SK_HISTOGRAM_MEMORY_KB("VulkanMemoryAllocator.AmountAllocated", allocatedMemory >> 10); 2283cb93a386Sopenharmony_ci#endif 2284cb93a386Sopenharmony_ci} 2285cb93a386Sopenharmony_ci 2286cb93a386Sopenharmony_civoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, 2287cb93a386Sopenharmony_ci GrSurface* src, 2288cb93a386Sopenharmony_ci GrVkImage* dstImage, 2289cb93a386Sopenharmony_ci GrVkImage* srcImage, 2290cb93a386Sopenharmony_ci const SkIRect& srcRect, 2291cb93a386Sopenharmony_ci const SkIPoint& dstPoint) { 2292cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2293cb93a386Sopenharmony_ci return; 2294cb93a386Sopenharmony_ci } 2295cb93a386Sopenharmony_ci 2296cb93a386Sopenharmony_ci#ifdef SK_DEBUG 2297cb93a386Sopenharmony_ci int dstSampleCnt = dstImage->numSamples(); 2298cb93a386Sopenharmony_ci int srcSampleCnt = srcImage->numSamples(); 2299cb93a386Sopenharmony_ci bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid(); 2300cb93a386Sopenharmony_ci bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid(); 2301cb93a386Sopenharmony_ci VkFormat dstFormat = dstImage->imageFormat(); 2302cb93a386Sopenharmony_ci VkFormat srcFormat; 2303cb93a386Sopenharmony_ci SkAssertResult(dst->backendFormat().asVkFormat(&srcFormat)); 2304cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr, 2305cb93a386Sopenharmony_ci srcFormat, srcSampleCnt, srcHasYcbcr)); 2306cb93a386Sopenharmony_ci#endif 2307cb93a386Sopenharmony_ci if (src->isProtected() && !dst->isProtected()) { 2308cb93a386Sopenharmony_ci SkDebugf("Can't copy from protected memory to non-protected"); 2309cb93a386Sopenharmony_ci return; 2310cb93a386Sopenharmony_ci } 2311cb93a386Sopenharmony_ci 2312cb93a386Sopenharmony_ci // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if 2313cb93a386Sopenharmony_ci // the cache is flushed since it is only being written to. 2314cb93a386Sopenharmony_ci dstImage->setImageLayout(this, 2315cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 2316cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 2317cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 2318cb93a386Sopenharmony_ci false); 2319cb93a386Sopenharmony_ci 2320cb93a386Sopenharmony_ci srcImage->setImageLayout(this, 2321cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 2322cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, 2323cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 2324cb93a386Sopenharmony_ci false); 2325cb93a386Sopenharmony_ci 2326cb93a386Sopenharmony_ci VkImageCopy copyRegion; 2327cb93a386Sopenharmony_ci memset(©Region, 0, sizeof(VkImageCopy)); 2328cb93a386Sopenharmony_ci copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 2329cb93a386Sopenharmony_ci copyRegion.srcOffset = { srcRect.fLeft, srcRect.fTop, 0 }; 2330cb93a386Sopenharmony_ci copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 2331cb93a386Sopenharmony_ci copyRegion.dstOffset = { dstPoint.fX, dstPoint.fY, 0 }; 2332cb93a386Sopenharmony_ci copyRegion.extent = { (uint32_t)srcRect.width(), (uint32_t)srcRect.height(), 1 }; 2333cb93a386Sopenharmony_ci 2334cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src)); 2335cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst)); 2336cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyImage(this, 2337cb93a386Sopenharmony_ci srcImage, 2338cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 2339cb93a386Sopenharmony_ci dstImage, 2340cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 2341cb93a386Sopenharmony_ci 1, 2342cb93a386Sopenharmony_ci ©Region); 2343cb93a386Sopenharmony_ci 2344cb93a386Sopenharmony_ci SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, 2345cb93a386Sopenharmony_ci srcRect.width(), srcRect.height()); 2346cb93a386Sopenharmony_ci // The rect is already in device space so we pass in kTopLeft so no flip is done. 2347cb93a386Sopenharmony_ci this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect); 2348cb93a386Sopenharmony_ci} 2349cb93a386Sopenharmony_ci 2350cb93a386Sopenharmony_civoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst, 2351cb93a386Sopenharmony_ci GrSurface* src, 2352cb93a386Sopenharmony_ci GrVkImage* dstImage, 2353cb93a386Sopenharmony_ci GrVkImage* srcImage, 2354cb93a386Sopenharmony_ci const SkIRect& srcRect, 2355cb93a386Sopenharmony_ci const SkIPoint& dstPoint) { 2356cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2357cb93a386Sopenharmony_ci return; 2358cb93a386Sopenharmony_ci } 2359cb93a386Sopenharmony_ci 2360cb93a386Sopenharmony_ci#ifdef SK_DEBUG 2361cb93a386Sopenharmony_ci int dstSampleCnt = dstImage->numSamples(); 2362cb93a386Sopenharmony_ci int srcSampleCnt = srcImage->numSamples(); 2363cb93a386Sopenharmony_ci bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid(); 2364cb93a386Sopenharmony_ci bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid(); 2365cb93a386Sopenharmony_ci VkFormat dstFormat = dstImage->imageFormat(); 2366cb93a386Sopenharmony_ci VkFormat srcFormat; 2367cb93a386Sopenharmony_ci SkAssertResult(dst->backendFormat().asVkFormat(&srcFormat)); 2368cb93a386Sopenharmony_ci SkASSERT(this->vkCaps().canCopyAsBlit(dstFormat, 2369cb93a386Sopenharmony_ci dstSampleCnt, 2370cb93a386Sopenharmony_ci dstImage->isLinearTiled(), 2371cb93a386Sopenharmony_ci dstHasYcbcr, 2372cb93a386Sopenharmony_ci srcFormat, 2373cb93a386Sopenharmony_ci srcSampleCnt, 2374cb93a386Sopenharmony_ci srcImage->isLinearTiled(), 2375cb93a386Sopenharmony_ci srcHasYcbcr)); 2376cb93a386Sopenharmony_ci 2377cb93a386Sopenharmony_ci#endif 2378cb93a386Sopenharmony_ci if (src->isProtected() && !dst->isProtected()) { 2379cb93a386Sopenharmony_ci SkDebugf("Can't copy from protected memory to non-protected"); 2380cb93a386Sopenharmony_ci return; 2381cb93a386Sopenharmony_ci } 2382cb93a386Sopenharmony_ci 2383cb93a386Sopenharmony_ci dstImage->setImageLayout(this, 2384cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 2385cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 2386cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 2387cb93a386Sopenharmony_ci false); 2388cb93a386Sopenharmony_ci 2389cb93a386Sopenharmony_ci srcImage->setImageLayout(this, 2390cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 2391cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, 2392cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 2393cb93a386Sopenharmony_ci false); 2394cb93a386Sopenharmony_ci 2395cb93a386Sopenharmony_ci // Flip rect if necessary 2396cb93a386Sopenharmony_ci SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, srcRect.width(), 2397cb93a386Sopenharmony_ci srcRect.height()); 2398cb93a386Sopenharmony_ci 2399cb93a386Sopenharmony_ci VkImageBlit blitRegion; 2400cb93a386Sopenharmony_ci memset(&blitRegion, 0, sizeof(VkImageBlit)); 2401cb93a386Sopenharmony_ci blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 2402cb93a386Sopenharmony_ci blitRegion.srcOffsets[0] = { srcRect.fLeft, srcRect.fTop, 0 }; 2403cb93a386Sopenharmony_ci blitRegion.srcOffsets[1] = { srcRect.fRight, srcRect.fBottom, 1 }; 2404cb93a386Sopenharmony_ci blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 2405cb93a386Sopenharmony_ci blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 }; 2406cb93a386Sopenharmony_ci blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 }; 2407cb93a386Sopenharmony_ci 2408cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src)); 2409cb93a386Sopenharmony_ci this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst)); 2410cb93a386Sopenharmony_ci this->currentCommandBuffer()->blitImage(this, 2411cb93a386Sopenharmony_ci *srcImage, 2412cb93a386Sopenharmony_ci *dstImage, 2413cb93a386Sopenharmony_ci 1, 2414cb93a386Sopenharmony_ci &blitRegion, 2415cb93a386Sopenharmony_ci VK_FILTER_NEAREST); // We never scale so any filter works here 2416cb93a386Sopenharmony_ci 2417cb93a386Sopenharmony_ci // The rect is already in device space so we pass in kTopLeft so no flip is done. 2418cb93a386Sopenharmony_ci this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect); 2419cb93a386Sopenharmony_ci} 2420cb93a386Sopenharmony_ci 2421cb93a386Sopenharmony_civoid GrVkGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, 2422cb93a386Sopenharmony_ci const SkIPoint& dstPoint) { 2423cb93a386Sopenharmony_ci if (src->isProtected() && !dst->isProtected()) { 2424cb93a386Sopenharmony_ci SkDebugf("Can't copy from protected memory to non-protected"); 2425cb93a386Sopenharmony_ci return; 2426cb93a386Sopenharmony_ci } 2427cb93a386Sopenharmony_ci GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget()); 2428cb93a386Sopenharmony_ci this->resolveImage(dst, srcRT, srcRect, dstPoint); 2429cb93a386Sopenharmony_ci SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, 2430cb93a386Sopenharmony_ci srcRect.width(), srcRect.height()); 2431cb93a386Sopenharmony_ci // The rect is already in device space so we pass in kTopLeft so no flip is done. 2432cb93a386Sopenharmony_ci this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect); 2433cb93a386Sopenharmony_ci} 2434cb93a386Sopenharmony_ci 2435cb93a386Sopenharmony_cibool GrVkGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, 2436cb93a386Sopenharmony_ci const SkIPoint& dstPoint) { 2437cb93a386Sopenharmony_ci#ifdef SK_DEBUG 2438cb93a386Sopenharmony_ci if (GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget())) { 2439cb93a386Sopenharmony_ci SkASSERT(!srcRT->wrapsSecondaryCommandBuffer()); 2440cb93a386Sopenharmony_ci } 2441cb93a386Sopenharmony_ci if (GrVkRenderTarget* dstRT = static_cast<GrVkRenderTarget*>(dst->asRenderTarget())) { 2442cb93a386Sopenharmony_ci SkASSERT(!dstRT->wrapsSecondaryCommandBuffer()); 2443cb93a386Sopenharmony_ci } 2444cb93a386Sopenharmony_ci#endif 2445cb93a386Sopenharmony_ci if (src->isProtected() && !dst->isProtected()) { 2446cb93a386Sopenharmony_ci SkDebugf("Can't copy from protected memory to non-protected"); 2447cb93a386Sopenharmony_ci return false; 2448cb93a386Sopenharmony_ci } 2449cb93a386Sopenharmony_ci 2450cb93a386Sopenharmony_ci GrVkImage* dstImage; 2451cb93a386Sopenharmony_ci GrVkImage* srcImage; 2452cb93a386Sopenharmony_ci GrRenderTarget* dstRT = dst->asRenderTarget(); 2453cb93a386Sopenharmony_ci if (dstRT) { 2454cb93a386Sopenharmony_ci GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT); 2455cb93a386Sopenharmony_ci if (vkRT->wrapsSecondaryCommandBuffer()) { 2456cb93a386Sopenharmony_ci return false; 2457cb93a386Sopenharmony_ci } 2458cb93a386Sopenharmony_ci // This will technically return true for single sample rts that used DMSAA in which case we 2459cb93a386Sopenharmony_ci // don't have to pick the resolve attachment. But in that case the resolve and color 2460cb93a386Sopenharmony_ci // attachments will be the same anyways. 2461cb93a386Sopenharmony_ci if (this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) { 2462cb93a386Sopenharmony_ci dstImage = vkRT->resolveAttachment(); 2463cb93a386Sopenharmony_ci } else { 2464cb93a386Sopenharmony_ci dstImage = vkRT->colorAttachment(); 2465cb93a386Sopenharmony_ci } 2466cb93a386Sopenharmony_ci } else if (dst->asTexture()) { 2467cb93a386Sopenharmony_ci dstImage = static_cast<GrVkTexture*>(dst->asTexture())->textureImage(); 2468cb93a386Sopenharmony_ci } else { 2469cb93a386Sopenharmony_ci // The surface in a GrAttachment already 2470cb93a386Sopenharmony_ci dstImage = static_cast<GrVkImage*>(dst); 2471cb93a386Sopenharmony_ci } 2472cb93a386Sopenharmony_ci GrRenderTarget* srcRT = src->asRenderTarget(); 2473cb93a386Sopenharmony_ci if (srcRT) { 2474cb93a386Sopenharmony_ci GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(srcRT); 2475cb93a386Sopenharmony_ci // This will technically return true for single sample rts that used DMSAA in which case we 2476cb93a386Sopenharmony_ci // don't have to pick the resolve attachment. But in that case the resolve and color 2477cb93a386Sopenharmony_ci // attachments will be the same anyways. 2478cb93a386Sopenharmony_ci if (this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) { 2479cb93a386Sopenharmony_ci srcImage = vkRT->resolveAttachment(); 2480cb93a386Sopenharmony_ci } else { 2481cb93a386Sopenharmony_ci srcImage = vkRT->colorAttachment(); 2482cb93a386Sopenharmony_ci } 2483cb93a386Sopenharmony_ci } else if (src->asTexture()) { 2484cb93a386Sopenharmony_ci SkASSERT(src->asTexture()); 2485cb93a386Sopenharmony_ci srcImage = static_cast<GrVkTexture*>(src->asTexture())->textureImage(); 2486cb93a386Sopenharmony_ci } else { 2487cb93a386Sopenharmony_ci // The surface in a GrAttachment already 2488cb93a386Sopenharmony_ci srcImage = static_cast<GrVkImage*>(src); 2489cb93a386Sopenharmony_ci } 2490cb93a386Sopenharmony_ci 2491cb93a386Sopenharmony_ci VkFormat dstFormat = dstImage->imageFormat(); 2492cb93a386Sopenharmony_ci VkFormat srcFormat = srcImage->imageFormat(); 2493cb93a386Sopenharmony_ci 2494cb93a386Sopenharmony_ci int dstSampleCnt = dstImage->numSamples(); 2495cb93a386Sopenharmony_ci int srcSampleCnt = srcImage->numSamples(); 2496cb93a386Sopenharmony_ci 2497cb93a386Sopenharmony_ci bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid(); 2498cb93a386Sopenharmony_ci bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid(); 2499cb93a386Sopenharmony_ci 2500cb93a386Sopenharmony_ci if (this->vkCaps().canCopyAsResolve(dstFormat, dstSampleCnt, dstHasYcbcr, 2501cb93a386Sopenharmony_ci srcFormat, srcSampleCnt, srcHasYcbcr)) { 2502cb93a386Sopenharmony_ci this->copySurfaceAsResolve(dst, src, srcRect, dstPoint); 2503cb93a386Sopenharmony_ci return true; 2504cb93a386Sopenharmony_ci } 2505cb93a386Sopenharmony_ci 2506cb93a386Sopenharmony_ci if (this->vkCaps().canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr, 2507cb93a386Sopenharmony_ci srcFormat, srcSampleCnt, srcHasYcbcr)) { 2508cb93a386Sopenharmony_ci this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint); 2509cb93a386Sopenharmony_ci return true; 2510cb93a386Sopenharmony_ci } 2511cb93a386Sopenharmony_ci 2512cb93a386Sopenharmony_ci if (this->vkCaps().canCopyAsBlit(dstFormat, 2513cb93a386Sopenharmony_ci dstSampleCnt, 2514cb93a386Sopenharmony_ci dstImage->isLinearTiled(), 2515cb93a386Sopenharmony_ci dstHasYcbcr, 2516cb93a386Sopenharmony_ci srcFormat, 2517cb93a386Sopenharmony_ci srcSampleCnt, 2518cb93a386Sopenharmony_ci srcImage->isLinearTiled(), 2519cb93a386Sopenharmony_ci srcHasYcbcr)) { 2520cb93a386Sopenharmony_ci this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint); 2521cb93a386Sopenharmony_ci return true; 2522cb93a386Sopenharmony_ci } 2523cb93a386Sopenharmony_ci 2524cb93a386Sopenharmony_ci return false; 2525cb93a386Sopenharmony_ci} 2526cb93a386Sopenharmony_ci 2527cb93a386Sopenharmony_cibool GrVkGpu::onReadPixels(GrSurface* surface, 2528cb93a386Sopenharmony_ci SkIRect rect, 2529cb93a386Sopenharmony_ci GrColorType surfaceColorType, 2530cb93a386Sopenharmony_ci GrColorType dstColorType, 2531cb93a386Sopenharmony_ci void* buffer, 2532cb93a386Sopenharmony_ci size_t rowBytes) { 2533cb93a386Sopenharmony_ci if (surface->isProtected()) { 2534cb93a386Sopenharmony_ci return false; 2535cb93a386Sopenharmony_ci } 2536cb93a386Sopenharmony_ci 2537cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2538cb93a386Sopenharmony_ci return false; 2539cb93a386Sopenharmony_ci } 2540cb93a386Sopenharmony_ci 2541cb93a386Sopenharmony_ci GrVkImage* image = nullptr; 2542cb93a386Sopenharmony_ci GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget()); 2543cb93a386Sopenharmony_ci if (rt) { 2544cb93a386Sopenharmony_ci // Reading from render targets that wrap a secondary command buffer is not allowed since 2545cb93a386Sopenharmony_ci // it would require us to know the VkImage, which we don't have, as well as need us to 2546cb93a386Sopenharmony_ci // stop and start the VkRenderPass which we don't have access to. 2547cb93a386Sopenharmony_ci if (rt->wrapsSecondaryCommandBuffer()) { 2548cb93a386Sopenharmony_ci return false; 2549cb93a386Sopenharmony_ci } 2550cb93a386Sopenharmony_ci image = rt->nonMSAAAttachment(); 2551cb93a386Sopenharmony_ci } else { 2552cb93a386Sopenharmony_ci image = static_cast<GrVkTexture*>(surface->asTexture())->textureImage(); 2553cb93a386Sopenharmony_ci } 2554cb93a386Sopenharmony_ci 2555cb93a386Sopenharmony_ci if (!image) { 2556cb93a386Sopenharmony_ci return false; 2557cb93a386Sopenharmony_ci } 2558cb93a386Sopenharmony_ci 2559cb93a386Sopenharmony_ci if (dstColorType == GrColorType::kUnknown || 2560cb93a386Sopenharmony_ci dstColorType != this->vkCaps().transferColorType(image->imageFormat(), surfaceColorType)) { 2561cb93a386Sopenharmony_ci return false; 2562cb93a386Sopenharmony_ci } 2563cb93a386Sopenharmony_ci 2564cb93a386Sopenharmony_ci // Change layout of our target so it can be used as copy 2565cb93a386Sopenharmony_ci image->setImageLayout(this, 2566cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 2567cb93a386Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, 2568cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 2569cb93a386Sopenharmony_ci false); 2570cb93a386Sopenharmony_ci 2571cb93a386Sopenharmony_ci size_t bpp = GrColorTypeBytesPerPixel(dstColorType); 2572cb93a386Sopenharmony_ci if (GrVkFormatBytesPerBlock(image->imageFormat()) != bpp) { 2573cb93a386Sopenharmony_ci return false; 2574cb93a386Sopenharmony_ci } 2575cb93a386Sopenharmony_ci size_t tightRowBytes = bpp*rect.width(); 2576cb93a386Sopenharmony_ci 2577cb93a386Sopenharmony_ci VkBufferImageCopy region; 2578cb93a386Sopenharmony_ci memset(®ion, 0, sizeof(VkBufferImageCopy)); 2579cb93a386Sopenharmony_ci VkOffset3D offset = { rect.left(), rect.top(), 0 }; 2580cb93a386Sopenharmony_ci region.imageOffset = offset; 2581cb93a386Sopenharmony_ci region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 }; 2582cb93a386Sopenharmony_ci 2583cb93a386Sopenharmony_ci size_t transBufferRowBytes = bpp * region.imageExtent.width; 2584cb93a386Sopenharmony_ci size_t imageRows = region.imageExtent.height; 2585cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = this->getContext()->priv().resourceProvider(); 2586cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> transferBuffer = resourceProvider->createBuffer( 2587cb93a386Sopenharmony_ci transBufferRowBytes * imageRows, GrGpuBufferType::kXferGpuToCpu, 2588cb93a386Sopenharmony_ci kDynamic_GrAccessPattern); 2589cb93a386Sopenharmony_ci 2590cb93a386Sopenharmony_ci if (!transferBuffer) { 2591cb93a386Sopenharmony_ci return false; 2592cb93a386Sopenharmony_ci } 2593cb93a386Sopenharmony_ci 2594cb93a386Sopenharmony_ci GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get()); 2595cb93a386Sopenharmony_ci 2596cb93a386Sopenharmony_ci // Copy the image to a buffer so we can map it to cpu memory 2597cb93a386Sopenharmony_ci region.bufferOffset = 0; 2598cb93a386Sopenharmony_ci region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below. 2599cb93a386Sopenharmony_ci region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images. 2600cb93a386Sopenharmony_ci region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 2601cb93a386Sopenharmony_ci 2602cb93a386Sopenharmony_ci this->currentCommandBuffer()->copyImageToBuffer(this, 2603cb93a386Sopenharmony_ci image, 2604cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 2605cb93a386Sopenharmony_ci transferBuffer, 2606cb93a386Sopenharmony_ci 1, 2607cb93a386Sopenharmony_ci ®ion); 2608cb93a386Sopenharmony_ci 2609cb93a386Sopenharmony_ci // make sure the copy to buffer has finished 2610cb93a386Sopenharmony_ci vkBuffer->addMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, 2611cb93a386Sopenharmony_ci VK_ACCESS_HOST_READ_BIT, 2612cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT, 2613cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_HOST_BIT, 2614cb93a386Sopenharmony_ci false); 2615cb93a386Sopenharmony_ci 2616cb93a386Sopenharmony_ci // We need to submit the current command buffer to the Queue and make sure it finishes before 2617cb93a386Sopenharmony_ci // we can copy the data out of the buffer. 2618cb93a386Sopenharmony_ci if (!this->submitCommandBuffer(kForce_SyncQueue)) { 2619cb93a386Sopenharmony_ci return false; 2620cb93a386Sopenharmony_ci } 2621cb93a386Sopenharmony_ci void* mappedMemory = transferBuffer->map(); 2622cb93a386Sopenharmony_ci 2623cb93a386Sopenharmony_ci SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, rect.height()); 2624cb93a386Sopenharmony_ci 2625cb93a386Sopenharmony_ci transferBuffer->unmap(); 2626cb93a386Sopenharmony_ci return true; 2627cb93a386Sopenharmony_ci} 2628cb93a386Sopenharmony_ci 2629cb93a386Sopenharmony_cibool GrVkGpu::beginRenderPass(const GrVkRenderPass* renderPass, 2630cb93a386Sopenharmony_ci sk_sp<const GrVkFramebuffer> framebuffer, 2631cb93a386Sopenharmony_ci const VkClearValue* colorClear, 2632cb93a386Sopenharmony_ci const GrSurface* target, 2633cb93a386Sopenharmony_ci const SkIRect& renderPassBounds, 2634cb93a386Sopenharmony_ci bool forSecondaryCB) { 2635cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2636cb93a386Sopenharmony_ci return false; 2637cb93a386Sopenharmony_ci } 2638cb93a386Sopenharmony_ci SkASSERT (!framebuffer->isExternal()); 2639cb93a386Sopenharmony_ci 2640cb93a386Sopenharmony_ci#ifdef SK_DEBUG 2641cb93a386Sopenharmony_ci uint32_t index; 2642cb93a386Sopenharmony_ci bool result = renderPass->colorAttachmentIndex(&index); 2643cb93a386Sopenharmony_ci SkASSERT(result && 0 == index); 2644cb93a386Sopenharmony_ci result = renderPass->stencilAttachmentIndex(&index); 2645cb93a386Sopenharmony_ci if (result) { 2646cb93a386Sopenharmony_ci SkASSERT(1 == index); 2647cb93a386Sopenharmony_ci } 2648cb93a386Sopenharmony_ci#endif 2649cb93a386Sopenharmony_ci VkClearValue clears[3]; 2650cb93a386Sopenharmony_ci int stencilIndex = renderPass->hasResolveAttachment() ? 2 : 1; 2651cb93a386Sopenharmony_ci clears[0].color = colorClear->color; 2652cb93a386Sopenharmony_ci clears[stencilIndex].depthStencil.depth = 0.0f; 2653cb93a386Sopenharmony_ci clears[stencilIndex].depthStencil.stencil = 0; 2654cb93a386Sopenharmony_ci 2655cb93a386Sopenharmony_ci return this->currentCommandBuffer()->beginRenderPass( 2656cb93a386Sopenharmony_ci this, renderPass, std::move(framebuffer), clears, target, renderPassBounds, forSecondaryCB); 2657cb93a386Sopenharmony_ci} 2658cb93a386Sopenharmony_ci 2659cb93a386Sopenharmony_civoid GrVkGpu::endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin, 2660cb93a386Sopenharmony_ci const SkIRect& bounds) { 2661cb93a386Sopenharmony_ci // We had a command buffer when we started the render pass, we should have one now as well. 2662cb93a386Sopenharmony_ci SkASSERT(this->currentCommandBuffer()); 2663cb93a386Sopenharmony_ci this->currentCommandBuffer()->endRenderPass(this); 2664cb93a386Sopenharmony_ci this->didWriteToSurface(target, origin, &bounds); 2665cb93a386Sopenharmony_ci} 2666cb93a386Sopenharmony_ci 2667cb93a386Sopenharmony_cibool GrVkGpu::checkVkResult(VkResult result) { 2668cb93a386Sopenharmony_ci switch (result) { 2669cb93a386Sopenharmony_ci case VK_SUCCESS: 2670cb93a386Sopenharmony_ci return true; 2671cb93a386Sopenharmony_ci case VK_ERROR_DEVICE_LOST: 2672cb93a386Sopenharmony_ci#ifdef SKIA_DFX_FOR_OHOS 2673cb93a386Sopenharmony_ci { 2674cb93a386Sopenharmony_ci auto context = getContext(); 2675cb93a386Sopenharmony_ci if (context) { 2676cb93a386Sopenharmony_ci auto cache = context->priv().getResourceCache(); 2677cb93a386Sopenharmony_ci if (cache) { 2678cb93a386Sopenharmony_ci auto cacheInfo = cache->cacheInfo(); 2679cb93a386Sopenharmony_ci SK_LOGE("GrVkGpu::checkVkResult VK_ERROR_DEVICE_LOST, cacheInfo = %{public}s", 2680cb93a386Sopenharmony_ci cacheInfo.c_str()); 2681cb93a386Sopenharmony_ci } 2682cb93a386Sopenharmony_ci } 2683cb93a386Sopenharmony_ci } 2684cb93a386Sopenharmony_ci#endif 2685cb93a386Sopenharmony_ci fDeviceIsLost = true; 2686cb93a386Sopenharmony_ci return false; 2687cb93a386Sopenharmony_ci case VK_ERROR_OUT_OF_DEVICE_MEMORY: 2688cb93a386Sopenharmony_ci case VK_ERROR_OUT_OF_HOST_MEMORY: 2689cb93a386Sopenharmony_ci this->setOOMed(); 2690cb93a386Sopenharmony_ci return false; 2691cb93a386Sopenharmony_ci default: 2692cb93a386Sopenharmony_ci return false; 2693cb93a386Sopenharmony_ci } 2694cb93a386Sopenharmony_ci} 2695cb93a386Sopenharmony_ci 2696cb93a386Sopenharmony_cistd::array<int, 2> GrVkGpu::GetHpsDimension(const SkBlurArg& blurArg) const 2697cb93a386Sopenharmony_ci{ 2698cb93a386Sopenharmony_ci int width = 0; 2699cb93a386Sopenharmony_ci int height = 0; 2700cb93a386Sopenharmony_ci VkRect2D srcRegion; 2701cb93a386Sopenharmony_ci srcRegion.offset = { blurArg.srcRect.fLeft, blurArg.srcRect.fTop }; 2702cb93a386Sopenharmony_ci srcRegion.extent = { (uint32_t)blurArg.srcRect.width(), (uint32_t)blurArg.srcRect.height() }; 2703cb93a386Sopenharmony_ci 2704cb93a386Sopenharmony_ci VkRect2D dstRegion; 2705cb93a386Sopenharmony_ci dstRegion.offset = { blurArg.dstRect.fLeft, blurArg.dstRect.fTop }; 2706cb93a386Sopenharmony_ci dstRegion.extent = { (uint32_t)blurArg.dstRect.width(), (uint32_t)blurArg.dstRect.height() }; 2707cb93a386Sopenharmony_ci 2708cb93a386Sopenharmony_ci VkDrawBlurImageInfoHUAWEI drawBlurImageInfo {}; 2709cb93a386Sopenharmony_ci drawBlurImageInfo.sType = VkStructureTypeHUAWEI::VK_STRUCTURE_TYPE_DRAW_BLUR_IMAGE_INFO_HUAWEI; 2710cb93a386Sopenharmony_ci drawBlurImageInfo.pNext = nullptr; 2711cb93a386Sopenharmony_ci drawBlurImageInfo.sigma = blurArg.sigma; 2712cb93a386Sopenharmony_ci drawBlurImageInfo.srcRegion = srcRegion; 2713cb93a386Sopenharmony_ci drawBlurImageInfo.dstRegion = dstRegion; 2714cb93a386Sopenharmony_ci drawBlurImageInfo.srcImageView = VK_NULL_HANDLE; 2715cb93a386Sopenharmony_ci 2716cb93a386Sopenharmony_ci VkRect2D hpsDimension {}; 2717cb93a386Sopenharmony_ci auto grVkInterface = this->vkInterface(); 2718cb93a386Sopenharmony_ci if (grVkInterface != nullptr && grVkInterface->fFunctions.fGetBlurImageSizeHUAWEI != nullptr) { 2719cb93a386Sopenharmony_ci VK_CALL(GetBlurImageSizeHUAWEI(this->device(), &drawBlurImageInfo, &hpsDimension)); 2720cb93a386Sopenharmony_ci width = static_cast<int>(hpsDimension.extent.width); 2721cb93a386Sopenharmony_ci height = static_cast<int>(hpsDimension.extent.height); 2722cb93a386Sopenharmony_ci } 2723cb93a386Sopenharmony_ci 2724cb93a386Sopenharmony_ci std::array<int, 2> res = {width, height}; // There are 2 variables here. 2725cb93a386Sopenharmony_ci return res; 2726cb93a386Sopenharmony_ci} 2727cb93a386Sopenharmony_ci 2728cb93a386Sopenharmony_civoid GrVkGpu::dumpVmaStats(SkString *out) { 2729cb93a386Sopenharmony_ci if (out == nullptr) { 2730cb93a386Sopenharmony_ci return; 2731cb93a386Sopenharmony_ci } 2732cb93a386Sopenharmony_ci out->appendf("dumpVmaCacheStats:\n"); 2733cb93a386Sopenharmony_ci fMemoryAllocatorCacheImage->dumpVmaStats(out, "\n"); 2734cb93a386Sopenharmony_ci} 2735cb93a386Sopenharmony_ci 2736cb93a386Sopenharmony_ci// OH ISSUE: asyn memory reclaimer 2737cb93a386Sopenharmony_civoid GrVkGpu::setGpuMemoryAsyncReclaimerSwitch(bool enabled) 2738cb93a386Sopenharmony_ci{ 2739cb93a386Sopenharmony_ci if (!fMemoryReclaimer) { 2740cb93a386Sopenharmony_ci fMemoryReclaimer = std::make_unique<GrVkMemoryReclaimer>(); 2741cb93a386Sopenharmony_ci } 2742cb93a386Sopenharmony_ci fMemoryReclaimer->setGpuMemoryAsyncReclaimerSwitch(enabled); 2743cb93a386Sopenharmony_ci} 2744cb93a386Sopenharmony_ci 2745cb93a386Sopenharmony_ci// OH ISSUE: asyn memory reclaimer 2746cb93a386Sopenharmony_civoid GrVkGpu::flushGpuMemoryInWaitQueue() 2747cb93a386Sopenharmony_ci{ 2748cb93a386Sopenharmony_ci if (fMemoryReclaimer) { 2749cb93a386Sopenharmony_ci fMemoryReclaimer->flushGpuMemoryInWaitQueue(); 2750cb93a386Sopenharmony_ci } 2751cb93a386Sopenharmony_ci} 2752cb93a386Sopenharmony_ci 2753cb93a386Sopenharmony_ci 2754cb93a386Sopenharmony_ci#ifdef SKIA_DFX_FOR_OHOS 2755cb93a386Sopenharmony_civoid GrVkGpu::addAllocImageBytes(size_t bytes) 2756cb93a386Sopenharmony_ci{ 2757cb93a386Sopenharmony_ci auto cache = getContext()->priv().getResourceCache(); 2758cb93a386Sopenharmony_ci if (!cache) { 2759cb93a386Sopenharmony_ci return; 2760cb93a386Sopenharmony_ci } 2761cb93a386Sopenharmony_ci cache->addAllocImageBytes(bytes); 2762cb93a386Sopenharmony_ci} 2763cb93a386Sopenharmony_ci 2764cb93a386Sopenharmony_civoid GrVkGpu::removeAllocImageBytes(size_t bytes) 2765cb93a386Sopenharmony_ci{ 2766cb93a386Sopenharmony_ci auto cache = getContext()->priv().getResourceCache(); 2767cb93a386Sopenharmony_ci if (!cache) { 2768cb93a386Sopenharmony_ci return; 2769cb93a386Sopenharmony_ci } 2770cb93a386Sopenharmony_ci cache->removeAllocImageBytes(bytes); 2771cb93a386Sopenharmony_ci} 2772cb93a386Sopenharmony_ci 2773cb93a386Sopenharmony_civoid GrVkGpu::addAllocBufferBytes(size_t bytes) 2774cb93a386Sopenharmony_ci{ 2775cb93a386Sopenharmony_ci auto cache = getContext()->priv().getResourceCache(); 2776cb93a386Sopenharmony_ci if (!cache) { 2777cb93a386Sopenharmony_ci return; 2778cb93a386Sopenharmony_ci } 2779cb93a386Sopenharmony_ci cache->addAllocBufferBytes(bytes); 2780cb93a386Sopenharmony_ci} 2781cb93a386Sopenharmony_ci 2782cb93a386Sopenharmony_civoid GrVkGpu::removeAllocBufferBytes(size_t bytes) 2783cb93a386Sopenharmony_ci{ 2784cb93a386Sopenharmony_ci auto cache = getContext()->priv().getResourceCache(); 2785cb93a386Sopenharmony_ci if (!cache) { 2786cb93a386Sopenharmony_ci return; 2787cb93a386Sopenharmony_ci } 2788cb93a386Sopenharmony_ci cache->removeAllocBufferBytes(bytes); 2789cb93a386Sopenharmony_ci} 2790cb93a386Sopenharmony_ci#endif 2791cb93a386Sopenharmony_ci 2792cb93a386Sopenharmony_civoid GrVkGpu::submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> buffer) { 2793cb93a386Sopenharmony_ci if (!this->currentCommandBuffer()) { 2794cb93a386Sopenharmony_ci return; 2795cb93a386Sopenharmony_ci } 2796cb93a386Sopenharmony_ci this->currentCommandBuffer()->executeCommands(this, std::move(buffer)); 2797cb93a386Sopenharmony_ci} 2798cb93a386Sopenharmony_ci 2799cb93a386Sopenharmony_civoid GrVkGpu::submit(GrOpsRenderPass* renderPass) { 2800cb93a386Sopenharmony_ci SkASSERT(fCachedOpsRenderPass.get() == renderPass); 2801cb93a386Sopenharmony_ci 2802cb93a386Sopenharmony_ci fCachedOpsRenderPass->submit(); 2803cb93a386Sopenharmony_ci fCachedOpsRenderPass->reset(); 2804cb93a386Sopenharmony_ci} 2805cb93a386Sopenharmony_ci 2806cb93a386Sopenharmony_ciGrFence SK_WARN_UNUSED_RESULT GrVkGpu::insertFence() { 2807cb93a386Sopenharmony_ci VkFenceCreateInfo createInfo; 2808cb93a386Sopenharmony_ci memset(&createInfo, 0, sizeof(VkFenceCreateInfo)); 2809cb93a386Sopenharmony_ci createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 2810cb93a386Sopenharmony_ci createInfo.pNext = nullptr; 2811cb93a386Sopenharmony_ci createInfo.flags = 0; 2812cb93a386Sopenharmony_ci VkFence fence = VK_NULL_HANDLE; 2813cb93a386Sopenharmony_ci VkResult result; 2814cb93a386Sopenharmony_ci 2815cb93a386Sopenharmony_ci VK_CALL_RET(result, CreateFence(this->device(), &createInfo, nullptr, &fence)); 2816cb93a386Sopenharmony_ci if (result != VK_SUCCESS) { 2817cb93a386Sopenharmony_ci return 0; 2818cb93a386Sopenharmony_ci } 2819cb93a386Sopenharmony_ci VK_CALL_RET(result, QueueSubmit(this->queue(), 0, nullptr, fence)); 2820cb93a386Sopenharmony_ci if (result != VK_SUCCESS) { 2821cb93a386Sopenharmony_ci VK_CALL(DestroyFence(this->device(), fence, nullptr)); 2822cb93a386Sopenharmony_ci return 0; 2823cb93a386Sopenharmony_ci } 2824cb93a386Sopenharmony_ci 2825cb93a386Sopenharmony_ci static_assert(sizeof(GrFence) >= sizeof(VkFence)); 2826cb93a386Sopenharmony_ci return (GrFence)fence; 2827cb93a386Sopenharmony_ci} 2828cb93a386Sopenharmony_ci 2829cb93a386Sopenharmony_cibool GrVkGpu::waitFence(GrFence fence) { 2830cb93a386Sopenharmony_ci SkASSERT(VK_NULL_HANDLE != (VkFence)fence); 2831cb93a386Sopenharmony_ci 2832cb93a386Sopenharmony_ci VkResult result; 2833cb93a386Sopenharmony_ci VK_CALL_RET(result, WaitForFences(this->device(), 1, (VkFence*)&fence, VK_TRUE, 0)); 2834cb93a386Sopenharmony_ci return (VK_SUCCESS == result); 2835cb93a386Sopenharmony_ci} 2836cb93a386Sopenharmony_ci 2837cb93a386Sopenharmony_civoid GrVkGpu::deleteFence(GrFence fence) const { 2838cb93a386Sopenharmony_ci VK_CALL(DestroyFence(this->device(), (VkFence)fence, nullptr)); 2839cb93a386Sopenharmony_ci} 2840cb93a386Sopenharmony_ci 2841cb93a386Sopenharmony_cistd::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT GrVkGpu::makeSemaphore(bool isOwned) { 2842cb93a386Sopenharmony_ci return GrVkSemaphore::Make(this, isOwned); 2843cb93a386Sopenharmony_ci} 2844cb93a386Sopenharmony_ci 2845cb93a386Sopenharmony_cistd::unique_ptr<GrSemaphore> GrVkGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore, 2846cb93a386Sopenharmony_ci GrSemaphoreWrapType wrapType, 2847cb93a386Sopenharmony_ci GrWrapOwnership ownership) { 2848cb93a386Sopenharmony_ci return GrVkSemaphore::MakeWrapped(this, semaphore.vkSemaphore(), wrapType, ownership); 2849cb93a386Sopenharmony_ci} 2850cb93a386Sopenharmony_ci 2851cb93a386Sopenharmony_civoid GrVkGpu::insertSemaphore(GrSemaphore* semaphore) { 2852cb93a386Sopenharmony_ci SkASSERT(semaphore); 2853cb93a386Sopenharmony_ci 2854cb93a386Sopenharmony_ci GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore); 2855cb93a386Sopenharmony_ci 2856cb93a386Sopenharmony_ci GrVkSemaphore::Resource* resource = vkSem->getResource(); 2857cb93a386Sopenharmony_ci if (resource->shouldSignal()) { 2858cb93a386Sopenharmony_ci resource->ref(); 2859cb93a386Sopenharmony_ci fSemaphoresToSignal.push_back(resource); 2860cb93a386Sopenharmony_ci } 2861cb93a386Sopenharmony_ci} 2862cb93a386Sopenharmony_ci 2863cb93a386Sopenharmony_civoid GrVkGpu::waitSemaphore(GrSemaphore* semaphore) { 2864cb93a386Sopenharmony_ci SkASSERT(semaphore); 2865cb93a386Sopenharmony_ci 2866cb93a386Sopenharmony_ci GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore); 2867cb93a386Sopenharmony_ci 2868cb93a386Sopenharmony_ci GrVkSemaphore::Resource* resource = vkSem->getResource(); 2869cb93a386Sopenharmony_ci if (resource->shouldWait()) { 2870cb93a386Sopenharmony_ci resource->ref(); 2871cb93a386Sopenharmony_ci fSemaphoresToWaitOn.push_back(resource); 2872cb93a386Sopenharmony_ci } 2873cb93a386Sopenharmony_ci} 2874cb93a386Sopenharmony_ci 2875cb93a386Sopenharmony_cistd::unique_ptr<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* texture) { 2876cb93a386Sopenharmony_ci SkASSERT(texture); 2877cb93a386Sopenharmony_ci GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage(); 2878cb93a386Sopenharmony_ci vkTexture->setImageLayout(this, 2879cb93a386Sopenharmony_ci VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 2880cb93a386Sopenharmony_ci VK_ACCESS_SHADER_READ_BIT, 2881cb93a386Sopenharmony_ci VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 2882cb93a386Sopenharmony_ci false); 2883cb93a386Sopenharmony_ci // TODO: should we have a way to notify the caller that this has failed? Currently if the submit 2884cb93a386Sopenharmony_ci // fails (caused by DEVICE_LOST) this will just cause us to fail the next use of the gpu. 2885cb93a386Sopenharmony_ci // Eventually we will abandon the whole GPU if this fails. 2886cb93a386Sopenharmony_ci this->submitToGpu(false); 2887cb93a386Sopenharmony_ci 2888cb93a386Sopenharmony_ci // The image layout change serves as a barrier, so no semaphore is needed. 2889cb93a386Sopenharmony_ci // If we ever decide we need to return a semaphore here, we need to make sure GrVkSemaphore is 2890cb93a386Sopenharmony_ci // thread safe so that only the first thread that tries to use the semaphore actually submits 2891cb93a386Sopenharmony_ci // it. This additionally would also require thread safety in command buffer submissions to 2892cb93a386Sopenharmony_ci // queues in general. 2893cb93a386Sopenharmony_ci return nullptr; 2894cb93a386Sopenharmony_ci} 2895cb93a386Sopenharmony_ci 2896cb93a386Sopenharmony_civoid GrVkGpu::addDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) { 2897cb93a386Sopenharmony_ci fDrawables.emplace_back(std::move(drawable)); 2898cb93a386Sopenharmony_ci} 2899cb93a386Sopenharmony_ci 2900cb93a386Sopenharmony_civoid GrVkGpu::storeVkPipelineCacheData() { 2901cb93a386Sopenharmony_ci if (this->getContext()->priv().getPersistentCache()) { 2902cb93a386Sopenharmony_ci this->resourceProvider().storePipelineCacheData(); 2903cb93a386Sopenharmony_ci } 2904cb93a386Sopenharmony_ci} 2905