GrVkGpu.cpp revision a584de966a4f7ab71f3f07077cf1e226def9d730
1164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/* 2164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * Copyright 2015 Google Inc. 3164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * 4164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * Use of this source code is governed by a BSD-style license that can be 5164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * found in the LICENSE file. 6164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel */ 7164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 8164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkGpu.h" 9164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 10164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrContextOptions.h" 11164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGeometryProcessor.h" 12164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGpuResourceCacheAccess.h" 130e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel#include "GrMesh.h" 14164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrPipeline.h" 15164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrRenderTargetPriv.h" 16164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrSurfacePriv.h" 17164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrTexturePriv.h" 18164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 19164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkCommandBuffer.h" 20066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel#include "GrVkGpuCommandBuffer.h" 21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImage.h" 22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkIndexBuffer.h" 23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h" 24164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h" 2522281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel#include "GrVkPipelineState.h" 26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h" 27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h" 28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h" 29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h" 30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h" 31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h" 32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "SkConfig8888.h" 34900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth#include "SkMipMap.h" 35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h" 37fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h" 38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X) 40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X) 41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X) 42164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 43d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS 44d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( 45d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth VkDebugReportFlagsEXT flags, 46d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth VkDebugReportObjectTypeEXT objectType, 47d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth uint64_t object, 48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth size_t location, 49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth int32_t messageCode, 50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth const char* pLayerPrefix, 51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth const char* pMessage, 52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth void* pUserData) { 53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { 58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } else { 60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } 62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth return VK_FALSE; 63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth} 64d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif 65d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth 66633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options, 67633b35657c964c32e7010b14bb2d396b4a764c52jvanverth GrContext* context) { 68dc0fcd41e75682a8bfd5e285d684461475226330bsalomon const GrVkBackendContext* vkBackendContext = 69dc0fcd41e75682a8bfd5e285d684461475226330bsalomon reinterpret_cast<const GrVkBackendContext*>(backendContext); 70633b35657c964c32e7010b14bb2d396b4a764c52jvanverth if (!vkBackendContext) { 71dc0fcd41e75682a8bfd5e285d684461475226330bsalomon vkBackendContext = GrVkBackendContext::Create(); 72633b35657c964c32e7010b14bb2d396b4a764c52jvanverth if (!vkBackendContext) { 73633b35657c964c32e7010b14bb2d396b4a764c52jvanverth return nullptr; 74164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 75633b35657c964c32e7010b14bb2d396b4a764c52jvanverth } else { 76633b35657c964c32e7010b14bb2d396b4a764c52jvanverth vkBackendContext->ref(); 77164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 78164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 79633b35657c964c32e7010b14bb2d396b4a764c52jvanverth return new GrVkGpu(context, options, vkBackendContext); 80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 83164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 849d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options, 85633b35657c964c32e7010b14bb2d396b4a764c52jvanverth const GrVkBackendContext* backendCtx) 86164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel : INHERITED(context) 87633b35657c964c32e7010b14bb2d396b4a764c52jvanverth , fDevice(backendCtx->fDevice) 88633b35657c964c32e7010b14bb2d396b4a764c52jvanverth , fQueue(backendCtx->fQueue) 89633b35657c964c32e7010b14bb2d396b4a764c52jvanverth , fResourceProvider(this) { 90633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fBackendContext.reset(backendCtx); 91164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 92d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS 93419ca64f0f800dc098369b5aa5a604acd017b240brianosman fCallback = VK_NULL_HANDLE; 94fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) { 95fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth // Setup callback creation information 96d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth VkDebugReportCallbackCreateInfoEXT callbackCreateInfo; 97d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 98d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.pNext = nullptr; 99d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 100ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel VK_DEBUG_REPORT_WARNING_BIT_EXT | 101d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth //VK_DEBUG_REPORT_INFORMATION_BIT_EXT | 102d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth //VK_DEBUG_REPORT_DEBUG_BIT_EXT | 103b4aa36211ca66ef127ac2954108742af1ead5082egdaniel VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 104d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.pfnCallback = &DebugReportCallback; 105d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.pUserData = nullptr; 106d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth 107fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth // Register the callback 108a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT( 109a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback)); 110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } 111d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif 112633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 113633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCompiler = shaderc_compiler_initialize(); 114633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 115fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice, 116c5ec1408298510410270ea67e895570ccfa76e54egdaniel backendCtx->fFeatures, backendCtx->fExtensions)); 117633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCaps.reset(SkRef(fVkCaps.get())); 118633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 119633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps)); 120633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 121633b35657c964c32e7010b14bb2d396b4a764c52jvanverth const VkCommandPoolCreateInfo cmdPoolInfo = { 122633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType 123633b35657c964c32e7010b14bb2d396b4a764c52jvanverth nullptr, // pNext 124633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // CmdPoolCreateFlags 125b0d4352ca610654f98c3c4ebc67ed9ad9c8c8493jvanverth backendCtx->fGraphicsQueueIndex, // queueFamilyIndex 126633b35657c964c32e7010b14bb2d396b4a764c52jvanverth }; 1279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr, 128633b35657c964c32e7010b14bb2d396b4a764c52jvanverth &fCmdPool)); 129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth // must call this after creating the CommandPool 131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fResourceProvider.init(); 1329a6cf800bc392fb4ba5065efb64f5b0320098d1aegdaniel fCurrentCmdBuffer = fResourceProvider.createPrimaryCommandBuffer(); 133633b35657c964c32e7010b14bb2d396b4a764c52jvanverth SkASSERT(fCurrentCmdBuffer); 134633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCurrentCmdBuffer->begin(this); 1356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 1366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // set up our heaps 1376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kLinearImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024)); 13805dceabf3422b785b52439378aa5527c42c6ca18egdaniel // We want the OptimalImage_Heap to use a SubAlloc_strategy but it occasionally causes the 13905dceabf3422b785b52439378aa5527c42c6ca18egdaniel // device to run out of memory. Most likely this is caused by fragmentation in the device heap 14005dceabf3422b785b52439378aa5527c42c6ca18egdaniel // and we can't allocate more. Until we get a fix moving this to SingleAlloc. 14105dceabf3422b785b52439378aa5527c42c6ca18egdaniel fHeaps[kOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 64*1024*1024)); 1426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kSmallOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 2*1024*1024)); 1436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0)); 1446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0)); 1456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 64*1024)); 1466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0)); 1476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024)); 148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() { 151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->end(this); 152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->unref(this); 153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // wait for all commands to finish 155ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth fResourceProvider.checkCommandBuffers(); 156a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth SkDEBUGCODE(VkResult res = ) VK_CALL(QueueWaitIdle(fQueue)); 157f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel 158f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel // On windows, sometimes calls to QueueWaitIdle return before actually signalling the fences 159f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel // on the command buffers even though they have completed. This causes an assert to fire when 160f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel // destroying the command buffers. Currently this ony seems to happen on windows, so we add a 161f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel // sleep to make sure the fence singals. 162f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#ifdef SK_DEBUG 163f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#if defined(SK_BUILD_FOR_WIN) 164f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel Sleep(10); // In milliseconds 165f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#else 166f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel // Uncomment if above bug happens on non windows build. 167f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel // sleep(1); // In seconds 168f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif 169f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif 170f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel 171ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth // VK_ERROR_DEVICE_LOST is acceptable when tearing down (see 4.2.4 in spec) 172ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res); 1739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // must call this just before we destroy the VkDevice 175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fResourceProvider.destroyResources(); 176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 177633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr)); 178633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 179633b35657c964c32e7010b14bb2d396b4a764c52jvanverth shaderc_compiler_release(fCompiler); 180633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 181633b35657c964c32e7010b14bb2d396b4a764c52jvanverth#ifdef ENABLE_VK_LAYERS 182a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth if (fCallback) { 183a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr)); 184419ca64f0f800dc098369b5aa5a604acd017b240brianosman fCallback = VK_NULL_HANDLE; 185a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth } 186d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif 187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/////////////////////////////////////////////////////////////////////////////// 190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1919cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielGrGpuCommandBuffer* GrVkGpu::createCommandBuffer( 1929cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel GrRenderTarget* target, 1939cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, 1949cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) { 1959cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); 1969cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo); 197066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel} 198066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel 199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) { 200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->end(this); 202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->submitToQueue(this, fQueue, sync); 204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fResourceProvider.checkCommandBuffers(); 205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Release old command buffer and create a new one 207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->unref(this); 2089a6cf800bc392fb4ba5065efb64f5b0320098d1aegdaniel fCurrentCmdBuffer = fResourceProvider.createPrimaryCommandBuffer(); 209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->begin(this); 212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/////////////////////////////////////////////////////////////////////////////// 2151bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern, 2161bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton const void* data) { 2171bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton GrBuffer* buff; 218397536cabe12a9936659870dd220c869789424bacdalton switch (type) { 219397536cabe12a9936659870dd220c869789424bacdalton case kVertex_GrBufferType: 220397536cabe12a9936659870dd220c869789424bacdalton SkASSERT(kDynamic_GrAccessPattern == accessPattern || 221397536cabe12a9936659870dd220c869789424bacdalton kStatic_GrAccessPattern == accessPattern); 2221bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); 223e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 224397536cabe12a9936659870dd220c869789424bacdalton case kIndex_GrBufferType: 225397536cabe12a9936659870dd220c869789424bacdalton SkASSERT(kDynamic_GrAccessPattern == accessPattern || 226397536cabe12a9936659870dd220c869789424bacdalton kStatic_GrAccessPattern == accessPattern); 2271bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); 228e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 229397536cabe12a9936659870dd220c869789424bacdalton case kXferCpuToGpu_GrBufferType: 230c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth SkASSERT(kStream_GrAccessPattern == accessPattern); 2311bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type); 232e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 233397536cabe12a9936659870dd220c869789424bacdalton case kXferGpuToCpu_GrBufferType: 234c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth SkASSERT(kStream_GrAccessPattern == accessPattern); 2351bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type); 236e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 237397536cabe12a9936659870dd220c869789424bacdalton default: 238397536cabe12a9936659870dd220c869789424bacdalton SkFAIL("Unknown buffer type."); 239397536cabe12a9936659870dd220c869789424bacdalton return nullptr; 240397536cabe12a9936659870dd220c869789424bacdalton } 2411bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton if (data && buff) { 2421bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff->updateData(data, size); 2431bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton } 2441bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton return buff; 245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, 249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig srcConfig, DrawPreference* drawPreference, 250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel WritePixelTempDrawInfo* tempDrawInfo) { 251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) { 252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 2554583ec51d9ddc830eeb854db068235be96ce59c4egdaniel GrRenderTarget* renderTarget = dstSurface->asRenderTarget(); 2564583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 2574583ec51d9ddc830eeb854db068235be96ce59c4egdaniel // Start off assuming no swizzling 2584583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fSwizzle = GrSwizzle::RGBA(); 2594583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fWriteConfig = srcConfig; 2604583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 2614583ec51d9ddc830eeb854db068235be96ce59c4egdaniel // These settings we will always want if a temp draw is performed. Initially set the config 2624583ec51d9ddc830eeb854db068235be96ce59c4egdaniel // to srcConfig, though that may be modified if we decide to do a R/B swap 2634583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags; 2644583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; 2654583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fWidth = width; 2664583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fHeight = height; 2674583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0; 2684583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; 2694583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 270d66110f5972169dbcda8932c3a9a001adff23df4egdaniel if (dstSurface->config() == srcConfig) { 271d66110f5972169dbcda8932c3a9a001adff23df4egdaniel return true; 272d66110f5972169dbcda8932c3a9a001adff23df4egdaniel } 273d66110f5972169dbcda8932c3a9a001adff23df4egdaniel 2744583ec51d9ddc830eeb854db068235be96ce59c4egdaniel if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config(), false)) { 2754583ec51d9ddc830eeb854db068235be96ce59c4egdaniel ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); 2764583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 2774583ec51d9ddc830eeb854db068235be96ce59c4egdaniel bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config(); 2784583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 2794583ec51d9ddc830eeb854db068235be96ce59c4egdaniel if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) { 2804583ec51d9ddc830eeb854db068235be96ce59c4egdaniel if (!this->vkCaps().isConfigTexturable(dstSurface->config())) { 2814583ec51d9ddc830eeb854db068235be96ce59c4egdaniel return false; 2824583ec51d9ddc830eeb854db068235be96ce59c4egdaniel } 2834583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config(); 2844583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); 2854583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fWriteConfig = dstSurface->config(); 2864583ec51d9ddc830eeb854db068235be96ce59c4egdaniel } 2874583ec51d9ddc830eeb854db068235be96ce59c4egdaniel return true; 288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 2904583ec51d9ddc830eeb854db068235be96ce59c4egdaniel return false; 291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface, 294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int left, int top, int width, int height, 295a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon GrPixelConfig config, 296a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon const SkTArray<GrMipLevel>& texels) { 297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture()); 298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!vkTex) { 299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 302900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Make sure we have at least the base level 30303509eafa3e25819ff69f4d4f339d46264820c38jvanverth if (texels.empty() || !texels.begin()->fPixels) { 30403509eafa3e25819ff69f4d4f339d46264820c38jvanverth return false; 30503509eafa3e25819ff69f4d4f339d46264820c38jvanverth } 306a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon 307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels. 308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { 309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool success = false; 313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) { 314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo() 315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(config == vkTex->desc().fConfig); 316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: add compressed texture support 317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // delete the following two lines and uncomment the two after that when ready 318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel vkTex->unref(); 319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width, 321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // height); 322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool linearTiling = vkTex->isLinearTiled(); 324900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (linearTiling) { 325900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (texels.count() > 1) { 326900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkDebugf("Can't upload mipmap data to linear tiled texture"); 327900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 328900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 329900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) { 330900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Need to change the layout to general in order to perform a host write 331900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth vkTex->setImageLayout(this, 332900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_GENERAL, 33350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_HOST_WRITE_BIT, 33450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_HOST_BIT, 335900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth false); 336bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel this->submitCommandBuffer(kForce_SyncQueue); 337900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 338900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataLinear(vkTex, left, top, width, height, config, 339900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth texels.begin()->fPixels, texels.begin()->fRowBytes); 340900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else { 341c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int newMipLevels = texels.count(); 34282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1; 34382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth if (newMipLevels != currentMipLevels) { 344c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if (!vkTex->reallocForMipmap(this, newMipLevels)) { 345900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 346900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 347900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 348900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels); 349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 3514583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 352900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return success; 353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 355900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, 356900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth int left, int top, int width, int height, 357900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrPixelConfig dataConfig, 358900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const void* data, 359900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth size_t rowBytes) { 360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(data); 361900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(tex->isLinearTiled()); 362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // If we're uploading compressed data then we should be using uploadCompressedTexData 364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); 365164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t bpp = GrBytesPerPixel(dataConfig); 367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrSurfaceDesc& desc = tex->desc(); 369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, 371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel &width, &height, &data, &rowBytes)) { 372164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 374164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t trimRowBytes = width * bpp; 375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 376900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() || 377900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout()); 378900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const VkImageSubresource subres = { 379900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_ASPECT_COLOR_BIT, 380900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 0, // mipLevel 381900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 0, // arraySlice 382900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth }; 383900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkSubresourceLayout layout; 384900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkResult err; 385900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 386900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const GrVkInterface* interface = this->vkInterface(); 387900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 388900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice, 389b2df0c2702329be6380a943d548e7377a51d8565egdaniel tex->image(), 390900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth &subres, 391900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth &layout)); 392900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 393900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top; 3941e305ba0d6a4237020d36234e9e286d3b0489401jvanverth const GrVkAlloc& alloc = tex->alloc(); 3951e305ba0d6a4237020d36234e9e286d3b0489401jvanverth VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp; 396900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkDeviceSize size = height*layout.rowPitch; 397900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth void* mapPtr; 3981e305ba0d6a4237020d36234e9e286d3b0489401jvanverth err = GR_VK_CALL(interface, MapMemory(fDevice, alloc.fMemory, offset, size, 0, &mapPtr)); 399900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (err) { 400900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 401900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 403900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { 404900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // copy into buffer by rows 405900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const char* srcRow = reinterpret_cast<const char*>(data); 406900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch; 407900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth for (int y = 0; y < height; y++) { 408900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(dstRow, srcRow, trimRowBytes); 409900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcRow += rowBytes; 410900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dstRow -= layout.rowPitch; 411900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 412900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else { 413900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy 414900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) { 415900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(mapPtr, data, trimRowBytes * height); 416164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 41788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes, 41888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel height); 419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 420900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 421164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 4221e305ba0d6a4237020d36234e9e286d3b0489401jvanverth GR_VK_CALL(interface, UnmapMemory(fDevice, alloc.fMemory)); 423900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 424900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return true; 425900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth} 426900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 427900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, 428a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth int left, int top, int width, int height, 429a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth GrPixelConfig dataConfig, 430a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth const SkTArray<GrMipLevel>& texels) { 431900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(!tex->isLinearTiled()); 432900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // The assumption is either that we have no mipmaps, or that our rect is the entire texture 433900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(1 == texels.count() || 434900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth (0 == left && 0 == top && width == tex->width() && height == tex->height())); 435900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 436900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // If we're uploading compressed data then we should be using uploadCompressedTexData 437900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); 438900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 439900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (width == 0 || height == 0) { 440900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 441900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 442900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 443900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const GrSurfaceDesc& desc = tex->desc(); 444900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); 445900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth size_t bpp = GrBytesPerPixel(dataConfig); 446900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 447900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // texels is const. 448c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes. 449c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // Because of this we need to make a non-const shallow copy of texels. 450c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkTArray<GrMipLevel> texelsShallowCopy(texels); 451900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 452c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0; 453c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentMipLevel--) { 454c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkASSERT(texelsShallowCopy[currentMipLevel].fPixels); 455900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 456900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 457900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Determine whether we need to flip when we copy into the buffer 458c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty()); 459900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 460c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // adjust any params (left, top, currentWidth, currentHeight 461900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // find the combined size of all the mip levels and the relative offset of 462900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // each into the collective buffer 463c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // Do the first level separately because we may need to adjust width and height 464c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // (for the non-mipped case). 465c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, 466c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &width, 467c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &height, 468c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[0].fPixels, 469c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[0].fRowBytes)) { 470c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth return false; 471c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth } 472c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count()); 473c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth individualMipOffsets.push_back(0); 474c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth size_t combinedBufferSize = width * bpp * height; 475c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int currentWidth = width; 476c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int currentHeight = height; 477c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) { 478c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentWidth = SkTMax(1, currentWidth/2); 479c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentHeight = SkTMax(1, currentHeight/2); 480c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, 481c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth ¤tWidth, 482c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth ¤tHeight, 483c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[currentMipLevel].fPixels, 484c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[currentMipLevel].fRowBytes)) { 485c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth return false; 486c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth } 487900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const size_t trimmedSize = currentWidth * bpp * currentHeight; 488900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth individualMipOffsets.push_back(combinedBufferSize); 489900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth combinedBufferSize += trimmedSize; 490900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 491900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 492900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // allocate buffer to hold our mip data 493900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrVkTransferBuffer* transferBuffer = 494900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type); 495900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 496900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth char* buffer = (char*) transferBuffer->map(); 497c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count()); 498900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 499c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentWidth = width; 500c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentHeight = height; 501c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) { 502900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const size_t trimRowBytes = currentWidth * bpp; 503c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; 504900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 505900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // copy data into the buffer, skipping the trailing bytes 506900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth char* dst = buffer + individualMipOffsets[currentMipLevel]; 507c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels; 508900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (flipY) { 509900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth src += (currentHeight - 1) * rowBytes; 510900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth for (int y = 0; y < currentHeight; y++) { 511900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(dst, src, trimRowBytes); 512900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth src -= rowBytes; 513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dst += trimRowBytes; 514164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else if (trimRowBytes == rowBytes) { 516900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(dst, src, trimRowBytes * currentHeight); 517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 518900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight); 519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 521900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkBufferImageCopy& region = regions.push_back(); 522164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(®ion, 0, sizeof(VkBufferImageCopy)); 523900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.bufferOffset = individualMipOffsets[currentMipLevel]; 524900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.bufferRowLength = currentWidth; 525900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.bufferImageHeight = currentHeight; 526cf942c4ef750712b624867cbb2217c14857db3c6bsalomon region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 }; 527c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 }; 528900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 }; 5294583ec51d9ddc830eeb854db068235be96ce59c4egdaniel 530c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentWidth = SkTMax(1, currentWidth/2); 531c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentHeight = SkTMax(1, currentHeight/2); 532900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 534900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer->unmap(); 535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 536900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // make sure the unmap has finished 537900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer->addMemoryBarrier(this, 538900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_ACCESS_HOST_WRITE_BIT, 539900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_ACCESS_TRANSFER_READ_BIT, 540900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 541900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 542900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth false); 543164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 544900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Change layout of our target so it can be copied to 545900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth tex->setImageLayout(this, 546900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 54750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_WRITE_BIT, 54850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 549900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth false); 550900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 551900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Copy the buffer to the image 552900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth fCurrentCmdBuffer->copyBufferToImage(this, 553900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer, 554900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth tex, 555900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 556900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth regions.count(), 557900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth regions.begin()); 558900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer->unref(); 559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 5642e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, 565a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon const SkTArray<GrMipLevel>& texels) { 566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); 567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat pixelFormat; 569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) { 570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!fVkCaps->isConfigTexturable(desc.fConfig)) { 574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 575164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 5770a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) { 5780a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel return nullptr; 5790a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel } 5800a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel 581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool linearTiling = false; 582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) { 583900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // we can't have a linear texture with a mipmap 584900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (texels.count() > 1) { 585900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkDebugf("Trying to create linear tiled texture with mipmap"); 586900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return nullptr; 587900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (fVkCaps->isConfigTexurableLinearly(desc.fConfig) && 589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) { 590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel linearTiling = true; 591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 593164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 595164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; 597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (renderTarget) { 598164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 600164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and 602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we 603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // will be using this texture in some copy or not. Also this assumes, as is the current case, 60462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // that all render targets in vulkan are also textures. If we change this practice of setting 605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // both bits, we must make sure to set the destination bit if we are uploading srcData to the 606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // texture. 607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 609a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : 610a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is 61362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set 614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // to 1. 615c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int mipLevels = texels.empty() ? 1 : texels.count(); 616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkImage::ImageDesc imageDesc; 617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fImageType = VK_IMAGE_TYPE_2D; 618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fFormat = pixelFormat; 619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fWidth = desc.fWidth; 620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fHeight = desc.fHeight; 621c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth imageDesc.fLevels = linearTiling ? 1 : mipLevels; 622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fSamples = 1; 623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; 624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fUsageFlags = usageFlags; 625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fMemProps = memProps; 626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* tex; 628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (renderTarget) { 6292e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc, 630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc); 631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 6322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc); 633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!tex) { 636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 639e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon if (!texels.empty()) { 640e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon SkASSERT(texels.begin()->fPixels); 641900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth bool success; 642900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (linearTiling) { 643900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, 644900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth texels.begin()->fPixels, texels.begin()->fRowBytes); 645900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else { 646900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, 647900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth texels); 648900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 649900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (!success) { 650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tex->unref(); 651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return tex; 656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 660a584de966a4f7ab71f3f07077cf1e226def9d730jvanverthbool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src, size_t srcSizeInBytes) { 661a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth 662a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth // Update the buffer 663a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth fCurrentCmdBuffer->updateBuffer(this, buffer, 0, srcSizeInBytes, src); 664a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth 665a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth return true; 666a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth} 667a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth 668a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth//////////////////////////////////////////////////////////////////////////////// 669a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth 670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) { 671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // By default, all textures in Vk use TopLeft 672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kDefault_GrSurfaceOrigin == origin) { 673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return kTopLeft_GrSurfaceOrigin; 674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return origin; 676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 679164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, 680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrWrapOwnership ownership) { 681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (0 == desc.fTextureHandle) { 682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int maxSize = this->caps()->maxTextureSize(); 686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (desc.fWidth > maxSize || desc.fHeight > maxSize) { 687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 690b2df0c2702329be6380a943d548e7377a51d8565egdaniel const GrVkImageInfo* info = reinterpret_cast<const GrVkImageInfo*>(desc.fTextureHandle); 6911e305ba0d6a4237020d36234e9e286d3b0489401jvanverth if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc.fMemory) { 692fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return nullptr; 693fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth } 694b2df0c2702329be6380a943d548e7377a51d8565egdaniel#ifdef SK_DEBUG 695b2df0c2702329be6380a943d548e7377a51d8565egdaniel VkFormat format; 696b2df0c2702329be6380a943d548e7377a51d8565egdaniel if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) { 697b2df0c2702329be6380a943d548e7377a51d8565egdaniel return nullptr; 698b2df0c2702329be6380a943d548e7377a51d8565egdaniel } 699b2df0c2702329be6380a943d548e7377a51d8565egdaniel SkASSERT(format == info->fFormat); 700b2df0c2702329be6380a943d548e7377a51d8565egdaniel#endif 701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 702164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurfaceDesc surfDesc; 703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // next line relies on GrBackendTextureDesc's flags matching GrTexture's 704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags; 705164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fWidth = desc.fWidth; 706164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fHeight = desc.fHeight; 707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fConfig = desc.fConfig; 708164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()); 709164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 710164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // In GL, Chrome assumes all textures are BottomLeft 711164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // In VK, we don't have this restriction 712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fOrigin = resolve_origin(desc.fOrigin); 713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* texture = nullptr; 715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (renderTarget) { 7169d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc, 717b2df0c2702329be6380a943d548e7377a51d8565egdaniel ownership, info); 718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 719b2df0c2702329be6380a943d548e7377a51d8565egdaniel texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, info); 720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!texture) { 722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return texture; 726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 728164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc, 729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrWrapOwnership ownership) { 7309d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 731b2df0c2702329be6380a943d548e7377a51d8565egdaniel const GrVkImageInfo* info = 732b2df0c2702329be6380a943d548e7377a51d8565egdaniel reinterpret_cast<const GrVkImageInfo*>(wrapDesc.fRenderTargetHandle); 733fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth if (VK_NULL_HANDLE == info->fImage || 7341e305ba0d6a4237020d36234e9e286d3b0489401jvanverth (VK_NULL_HANDLE == info->fAlloc.fMemory && kAdopt_GrWrapOwnership == ownership)) { 735fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return nullptr; 736fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth } 737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurfaceDesc desc; 739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fConfig = wrapDesc.fConfig; 740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fFlags = kCheckAllocation_GrSurfaceFlag; 741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fWidth = wrapDesc.fWidth; 742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fHeight = wrapDesc.fHeight; 743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount()); 744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fOrigin = resolve_origin(wrapDesc.fOrigin); 746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc, 7482e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen ownership, 749fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info); 750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (tgt && wrapDesc.fStencilBits) { 751164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) { 752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tgt->unref(); 753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return tgt; 757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 75962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverthvoid GrVkGpu::generateMipmap(GrVkTexture* tex) const { 760900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // don't do anything for linearly tiled textures (can't have mipmaps) 76162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth if (tex->isLinearTiled()) { 762900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkDebugf("Trying to create mipmap for linear tiled texture"); 76362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 76462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 76562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 76662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // We cannot generate mipmaps for images that are multisampled. 76762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // TODO: does it even make sense for rendertargets in general? 76862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth if (tex->asRenderTarget() && tex->asRenderTarget()->numColorSamples() > 1) { 76962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 77062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 77162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 77262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // determine if we can blit to and from this format 77362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth const GrVkCaps& caps = this->vkCaps(); 77462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth if (!caps.configCanBeDstofBlit(tex->config(), false) || 77562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth !caps.configCanBeSrcofBlit(tex->config(), false)) { 77662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 77762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 77862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 77962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // change the original image's layout 78062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 78150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); 78262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 78362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // grab handle to the original image resource 784b2df0c2702329be6380a943d548e7377a51d8565egdaniel const GrVkResource* oldResource = tex->resource(); 78562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource->ref(); 786b2df0c2702329be6380a943d548e7377a51d8565egdaniel VkImage oldImage = tex->image(); 78762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 78882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth // SkMipMap doesn't include the base level in the level count so we have to add 1 78982c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1; 79082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth if (!tex->reallocForMipmap(this, levelCount)) { 79162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource->unref(this); 79262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 79362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 79462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 79562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // change the new image's layout 79650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL, 79750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); 79862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 79962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // Blit original image 80062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth int width = tex->width(); 80162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth int height = tex->height(); 80262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 80362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkImageBlit blitRegion; 80462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth memset(&blitRegion, 0, sizeof(VkImageBlit)); 80562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 80662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcOffsets[0] = { 0, 0, 0 }; 807e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman blitRegion.srcOffsets[1] = { width, height, 1 }; 80882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 80962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstOffsets[0] = { 0, 0, 0 }; 810e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman blitRegion.dstOffsets[1] = { width, height, 1 }; 81162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 81262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth fCurrentCmdBuffer->blitImage(this, 81362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource, 814b2df0c2702329be6380a943d548e7377a51d8565egdaniel oldImage, 81562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 81662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth tex->resource(), 817b2df0c2702329be6380a943d548e7377a51d8565egdaniel tex->image(), 81850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_IMAGE_LAYOUT_GENERAL, 81962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 1, 82062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth &blitRegion, 82162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_FILTER_LINEAR); 82250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth 82350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth // setup memory barrier 824b2df0c2702329be6380a943d548e7377a51d8565egdaniel SkASSERT(GrVkFormatToPixelConfig(tex->imageFormat(), nullptr)); 82550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; 82650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VkImageMemoryBarrier imageMemoryBarrier = { 82750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 82850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth NULL, // pNext 82950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_WRITE_BIT, // outputMask 83050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_READ_BIT, // inputMask 83150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_IMAGE_LAYOUT_GENERAL, // oldLayout 83250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_IMAGE_LAYOUT_GENERAL, // newLayout 83350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 83450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex 835b2df0c2702329be6380a943d548e7377a51d8565egdaniel tex->image(), // image 83650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth { aspectFlags, 0, 1, 0, 1 } // subresourceRange 83750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth }; 83850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth 83962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // Blit the miplevels 84082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth uint32_t mipLevel = 1; 84182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth while (mipLevel < levelCount) { 84282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth int prevWidth = width; 84382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth int prevHeight = height; 84482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth width = SkTMax(1, width / 2); 84582c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth height = SkTMax(1, height / 2); 84682c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth 84750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1; 84850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 84950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth false, &imageMemoryBarrier); 85050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth 85150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 }; 85262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcOffsets[0] = { 0, 0, 0 }; 853e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 }; 85482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 }; 85562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstOffsets[0] = { 0, 0, 0 }; 856e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman blitRegion.dstOffsets[1] = { width, height, 1 }; 85762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth fCurrentCmdBuffer->blitImage(this, 858b2df0c2702329be6380a943d548e7377a51d8565egdaniel *tex, 859b2df0c2702329be6380a943d548e7377a51d8565egdaniel *tex, 86062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 1, 86162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth &blitRegion, 86262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_FILTER_LINEAR); 86382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth ++mipLevel; 86462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 86562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 86662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource->unref(this); 86762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth} 86862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 869164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 870164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 871164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt, 872164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int width, 873164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int height) { 874164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(width >= rt->width()); 875164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(height >= rt->height()); 876164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 877164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int samples = rt->numStencilSamples(); 878164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 8798f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat(); 880164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 881164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this, 882164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel width, 883164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel height, 884164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel samples, 885164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel sFmt)); 886164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fStats.incStencilAttachmentCreates(); 887164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return stencil; 888164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 889164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 890164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 891164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 892164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h, 8930a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel GrPixelConfig config, 8940a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel bool isRenderTarget) { 895164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 896164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat pixelFormat; 897164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { 898164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 899164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 900164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 901164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool linearTiling = false; 902164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!fVkCaps->isConfigTexturable(config)) { 903164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 904164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 905164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 9060a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) { 9070a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel return 0; 9080a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel } 9090a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel 9100a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel if (fVkCaps->isConfigTexurableLinearly(config) && 9110a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false))) { 912164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel linearTiling = true; 913164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 914164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 915164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Currently this is not supported since it requires a copy which has not yet been implemented. 916164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (srcData && !linearTiling) { 917164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 918164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 919164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 920164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; 921164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 922164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; 9230a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel if (isRenderTarget) { 9240a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 9250a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel } 926164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 927fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkImage image = VK_NULL_HANDLE; 9286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0 }; 929164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 930fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; 931fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling) 932fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth ? VK_IMAGE_LAYOUT_PREINITIALIZED 933fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth : VK_IMAGE_LAYOUT_UNDEFINED; 934fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 935fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth // Create Image 936fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkSampleCountFlagBits vkSamples; 937fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth if (!GrSampleCountToVkSampleCount(1, &vkSamples)) { 938fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return 0; 939fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth } 940fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 941fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth const VkImageCreateInfo imageCreateInfo = { 942fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType 943fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth NULL, // pNext 944fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 0, // VkImageCreateFlags 945fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_IMAGE_TYPE_2D, // VkImageType 946fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth pixelFormat, // VkFormat 947384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas { (uint32_t) w, (uint32_t) h, 1 }, // VkExtent3D 948fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 1, // mipLevels 949fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 1, // arrayLayers 950fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth vkSamples, // samples 951fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth imageTiling, // VkImageTiling 952fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth usageFlags, // VkImageUsageFlags 953fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode 954fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 0, // queueFamilyCount 955fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 0, // pQueueFamilyIndices 956fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth initialLayout // initialLayout 957fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth }; 958fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 959fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image)); 960fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 9616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) { 962fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(DestroyImage(this->device(), image, nullptr)); 963164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 964164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 965164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 966164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (srcData) { 967164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (linearTiling) { 968164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const VkImageSubresource subres = { 969164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_ASPECT_COLOR_BIT, 970164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 0, // mipLevel 971164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 0, // arraySlice 972164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel }; 973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkSubresourceLayout layout; 974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkResult err; 975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 976fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout)); 977164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 978164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* mapPtr; 9791e305ba0d6a4237020d36234e9e286d3b0489401jvanverth err = VK_CALL(MapMemory(fDevice, alloc.fMemory, alloc.fOffset, layout.rowPitch * h, 9801e305ba0d6a4237020d36234e9e286d3b0489401jvanverth 0, &mapPtr)); 981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (err) { 9826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkMemory::FreeImageMemory(this, linearTiling, alloc); 983fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(DestroyImage(this->device(), image, nullptr)); 984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 985164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 986164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t bpp = GrBytesPerPixel(config); 988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t rowCopyBytes = bpp * w; 989164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // If there is no padding on dst (layout.rowPitch) we can do a single memcopy. 990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // This assumes the srcData comes in with no padding. 991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (rowCopyBytes == layout.rowPitch) { 992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memcpy(mapPtr, srcData, rowCopyBytes * h); 993164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 994fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcData, rowCopyBytes, 995fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth rowCopyBytes, h); 996164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 9971e305ba0d6a4237020d36234e9e286d3b0489401jvanverth VK_CALL(UnmapMemory(fDevice, alloc.fMemory)); 998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 999164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: Add support for copying to optimal tiling 1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(false); 1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1003164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1004b2df0c2702329be6380a943d548e7377a51d8565egdaniel GrVkImageInfo* info = new GrVkImageInfo; 1005fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fImage = image; 1006fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fAlloc = alloc; 1007fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fImageTiling = imageTiling; 1008fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fImageLayout = initialLayout; 100958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel info->fFormat = pixelFormat; 10102af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth info->fLevelCount = 1; 1011fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 1012fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return (GrBackendObject)info; 1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const { 1016b2df0c2702329be6380a943d548e7377a51d8565egdaniel const GrVkImageInfo* backend = reinterpret_cast<const GrVkImageInfo*>(id); 1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 10181e305ba0d6a4237020d36234e9e286d3b0489401jvanverth if (backend && backend->fImage && backend->fAlloc.fMemory) { 1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkMemoryRequirements req; 1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(&req, 0, sizeof(req)); 1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice, 1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel backend->fImage, 1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel &req)); 1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: find a better check 1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // This will probably fail with a different driver 1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return (req.size > 0) && (req.size <= 8192 * 8192); 1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) { 10336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id); 1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (backend) { 1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!abandon) { 1036fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth // something in the command buffer may still be using this, so force submit 1037fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth this->submitCommandBuffer(kForce_SyncQueue); 10386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkImage::DestroyImageInfo(this, backend); 1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1040fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth delete backend; 1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask, 1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask, 1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool byRegion, 1049164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkMemoryBarrier* barrier) const { 1050164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 1051164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->pipelineBarrier(this, 1052164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1053164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1054164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel byRegion, 1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkCommandBuffer::kMemory_BarrierType, 1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel barrier); 1057164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask, 1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask, 1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool byRegion, 1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkBufferMemoryBarrier* barrier) const { 1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->pipelineBarrier(this, 1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel byRegion, 1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkCommandBuffer::kBufferMemory_BarrierType, 1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel barrier); 1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1071164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1072164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask, 1073164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask, 1074164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool byRegion, 1075164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageMemoryBarrier* barrier) const { 1076164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 1077164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->pipelineBarrier(this, 1078164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1079164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1080164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel byRegion, 1081164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkCommandBuffer::kImageMemory_BarrierType, 1082164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel barrier); 1083164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1084164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1085164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() { 1086164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Submit the current command buffer to the Queue 1087164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel this->submitCommandBuffer(kSkip_SyncQueue); 1088164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1089164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 10903d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) { 10913d5d9ac426ea926f37eaa47e13acf7492068667begdaniel if (nullptr == target) { 10923d5d9ac426ea926f37eaa47e13acf7492068667begdaniel return; 10933d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } 10943d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment(); 10953d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; 10963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkClearDepthStencilValue vkStencilColor; 10993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); 11003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkStencil->setImageLayout(this, 11023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 110350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_WRITE_BIT, 110450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 11053d5d9ac426ea926f37eaa47e13acf7492068667begdaniel false); 11063d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11073d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkImageSubresourceRange subRange; 11083d5d9ac426ea926f37eaa47e13acf7492068667begdaniel memset(&subRange, 0, sizeof(VkImageSubresourceRange)); 11093d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; 11103d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.baseMipLevel = 0; 11113d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.levelCount = 1; 11123d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.baseArrayLayer = 0; 11133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.layerCount = 1; 11143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a 11163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // draw. Thus we should look into using the load op functions on the render pass to clear out 11173d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // the stencil there. 11183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange); 11193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel} 11203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 1121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst, 1122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrSurface* src, 1123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrVkGpu* gpu) { 112417b892551465e5a44560a06e4b34dc3592b49622egdaniel // Currently we don't support msaa 112517b892551465e5a44560a06e4b34dc3592b49622egdaniel if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) || 112617b892551465e5a44560a06e4b34dc3592b49622egdaniel (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) { 112717b892551465e5a44560a06e4b34dc3592b49622egdaniel return false; 112817b892551465e5a44560a06e4b34dc3592b49622egdaniel } 112917b892551465e5a44560a06e4b34dc3592b49622egdaniel 113017b892551465e5a44560a06e4b34dc3592b49622egdaniel // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src 113117b892551465e5a44560a06e4b34dc3592b49622egdaniel // as image usage flags. 113217b892551465e5a44560a06e4b34dc3592b49622egdaniel if (src->origin() == dst->origin() && 113317b892551465e5a44560a06e4b34dc3592b49622egdaniel GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) { 1134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled 113817b892551465e5a44560a06e4b34dc3592b49622egdaniel // or the resolved image here? Im multisampled, Vulkan requires sample counts to be the same. 1139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, 1144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurface* src, 114517b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* dstImage, 114617b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* srcImage, 1147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIRect& srcRect, 1148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIPoint& dstPoint) { 1149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(can_copy_image(dst, src, this)); 1150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if 1152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // the cache is flushed since it is only being written to. 115317b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage->setImageLayout(this, 115450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 115550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_WRITE_BIT, 115650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 115750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth false); 1158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 115917b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage->setImageLayout(this, 116017b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 116150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_READ_BIT, 116250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 116317b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 1164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Flip rect if necessary 1166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkIRect srcVkRect = srcRect; 1167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int32_t dstY = dstPoint.fY; 1168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kBottomLeft_GrSurfaceOrigin == src->origin()) { 1170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin()); 1171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcVkRect.fTop = src->height() - srcRect.fBottom; 1172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcVkRect.fBottom = src->height() - srcRect.fTop; 1173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstY = dst->height() - dstPoint.fY - srcVkRect.height(); 1174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageCopy copyRegion; 1177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(©Region, 0, sizeof(VkImageCopy)); 1178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 1179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 }; 1180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 1181164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.dstOffset = { dstPoint.fX, dstY, 0 }; 1182c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel // The depth value of the extent is ignored according the vulkan spec for 2D images. However, on 1183c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel // at least the nexus 5X it seems to be checking it. Thus as a working around we must have the 1184c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel // depth value be 1. 1185c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 }; 1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->copyImage(this, 118817b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage, 1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 119017b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage, 1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1, 1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel ©Region); 1194900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 1195900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, 1196900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcRect.width(), srcRect.height()); 1197900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth this->didWriteToSurface(dst, &dstRect); 1198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 120017b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst, 120117b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrSurface* src, 120217b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkImage* dstImage, 120317b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkImage* srcImage, 120417b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkGpu* gpu) { 120517b892551465e5a44560a06e4b34dc3592b49622egdaniel // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src 120617b892551465e5a44560a06e4b34dc3592b49622egdaniel // as image usage flags. 120717b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkCaps& caps = gpu->vkCaps(); 120817b892551465e5a44560a06e4b34dc3592b49622egdaniel if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) || 120917b892551465e5a44560a06e4b34dc3592b49622egdaniel !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) { 121017b892551465e5a44560a06e4b34dc3592b49622egdaniel return false; 121117b892551465e5a44560a06e4b34dc3592b49622egdaniel } 121217b892551465e5a44560a06e4b34dc3592b49622egdaniel 121317b892551465e5a44560a06e4b34dc3592b49622egdaniel // We cannot blit images that are multisampled. Will need to figure out if we can blit the 121417b892551465e5a44560a06e4b34dc3592b49622egdaniel // resolved msaa though. 121517b892551465e5a44560a06e4b34dc3592b49622egdaniel if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) || 121617b892551465e5a44560a06e4b34dc3592b49622egdaniel (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) { 121717b892551465e5a44560a06e4b34dc3592b49622egdaniel return false; 121817b892551465e5a44560a06e4b34dc3592b49622egdaniel } 121917b892551465e5a44560a06e4b34dc3592b49622egdaniel 122017b892551465e5a44560a06e4b34dc3592b49622egdaniel return true; 122117b892551465e5a44560a06e4b34dc3592b49622egdaniel} 122217b892551465e5a44560a06e4b34dc3592b49622egdaniel 122317b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst, 122417b892551465e5a44560a06e4b34dc3592b49622egdaniel GrSurface* src, 122517b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* dstImage, 122617b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* srcImage, 122717b892551465e5a44560a06e4b34dc3592b49622egdaniel const SkIRect& srcRect, 122817b892551465e5a44560a06e4b34dc3592b49622egdaniel const SkIPoint& dstPoint) { 122917b892551465e5a44560a06e4b34dc3592b49622egdaniel SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this)); 123017b892551465e5a44560a06e4b34dc3592b49622egdaniel 123117b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage->setImageLayout(this, 123217b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 123350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_WRITE_BIT, 123450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 123517b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 123617b892551465e5a44560a06e4b34dc3592b49622egdaniel 123717b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage->setImageLayout(this, 123817b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 123950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_READ_BIT, 124050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 124117b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 124217b892551465e5a44560a06e4b34dc3592b49622egdaniel 124317b892551465e5a44560a06e4b34dc3592b49622egdaniel // Flip rect if necessary 124417b892551465e5a44560a06e4b34dc3592b49622egdaniel SkIRect srcVkRect; 12458af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fLeft = srcRect.fLeft; 12468af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fRight = srcRect.fRight; 124717b892551465e5a44560a06e4b34dc3592b49622egdaniel SkIRect dstRect; 124817b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fLeft = dstPoint.fX; 12498af936d3047208def585b7bc824f013b994f6312egdaniel dstRect.fRight = dstPoint.fX + srcRect.width(); 125017b892551465e5a44560a06e4b34dc3592b49622egdaniel 125117b892551465e5a44560a06e4b34dc3592b49622egdaniel if (kBottomLeft_GrSurfaceOrigin == src->origin()) { 125217b892551465e5a44560a06e4b34dc3592b49622egdaniel srcVkRect.fTop = src->height() - srcRect.fBottom; 125317b892551465e5a44560a06e4b34dc3592b49622egdaniel srcVkRect.fBottom = src->height() - srcRect.fTop; 125417b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 12558af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fTop = srcRect.fTop; 12568af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fBottom = srcRect.fBottom; 125717b892551465e5a44560a06e4b34dc3592b49622egdaniel } 125817b892551465e5a44560a06e4b34dc3592b49622egdaniel 125917b892551465e5a44560a06e4b34dc3592b49622egdaniel if (kBottomLeft_GrSurfaceOrigin == dst->origin()) { 126017b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height(); 126117b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 126217b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fTop = dstPoint.fY; 126317b892551465e5a44560a06e4b34dc3592b49622egdaniel } 126417b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fBottom = dstRect.fTop + srcVkRect.height(); 126517b892551465e5a44560a06e4b34dc3592b49622egdaniel 126617b892551465e5a44560a06e4b34dc3592b49622egdaniel // If we have different origins, we need to flip the top and bottom of the dst rect so that we 126717b892551465e5a44560a06e4b34dc3592b49622egdaniel // get the correct origintation of the copied data. 126817b892551465e5a44560a06e4b34dc3592b49622egdaniel if (src->origin() != dst->origin()) { 126917b892551465e5a44560a06e4b34dc3592b49622egdaniel SkTSwap(dstRect.fTop, dstRect.fBottom); 127017b892551465e5a44560a06e4b34dc3592b49622egdaniel } 127117b892551465e5a44560a06e4b34dc3592b49622egdaniel 127217b892551465e5a44560a06e4b34dc3592b49622egdaniel VkImageBlit blitRegion; 127317b892551465e5a44560a06e4b34dc3592b49622egdaniel memset(&blitRegion, 0, sizeof(VkImageBlit)); 127417b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 127517b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 }; 127617b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 0 }; 127717b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 127817b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 }; 127917b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 0 }; 128017b892551465e5a44560a06e4b34dc3592b49622egdaniel 128117b892551465e5a44560a06e4b34dc3592b49622egdaniel fCurrentCmdBuffer->blitImage(this, 1282b2df0c2702329be6380a943d548e7377a51d8565egdaniel *srcImage, 1283b2df0c2702329be6380a943d548e7377a51d8565egdaniel *dstImage, 128417b892551465e5a44560a06e4b34dc3592b49622egdaniel 1, 128517b892551465e5a44560a06e4b34dc3592b49622egdaniel &blitRegion, 128617b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_FILTER_NEAREST); // We never scale so any filter works here 1287900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 1288900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth this->didWriteToSurface(dst, &dstRect); 128917b892551465e5a44560a06e4b34dc3592b49622egdaniel} 129017b892551465e5a44560a06e4b34dc3592b49622egdaniel 1291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst, 1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrSurface* src, 1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrVkGpu* gpu) { 1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst, 1298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurface* src, 1299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIRect& srcRect, 1300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIPoint& dstPoint) { 1301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(false); 1302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst, 1305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurface* src, 1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIRect& srcRect, 1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIPoint& dstPoint) { 130817b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* dstImage; 130917b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* srcImage; 131017b892551465e5a44560a06e4b34dc3592b49622egdaniel if (dst->asTexture()) { 131117b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage = static_cast<GrVkTexture*>(dst->asTexture()); 131217b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 131317b892551465e5a44560a06e4b34dc3592b49622egdaniel SkASSERT(dst->asRenderTarget()); 131417b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage = static_cast<GrVkRenderTarget*>(dst->asRenderTarget()); 131517b892551465e5a44560a06e4b34dc3592b49622egdaniel } 131617b892551465e5a44560a06e4b34dc3592b49622egdaniel if (src->asTexture()) { 131717b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage = static_cast<GrVkTexture*>(src->asTexture()); 131817b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 131917b892551465e5a44560a06e4b34dc3592b49622egdaniel SkASSERT(src->asRenderTarget()); 132017b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage = static_cast<GrVkRenderTarget*>(src->asRenderTarget()); 132117b892551465e5a44560a06e4b34dc3592b49622egdaniel } 132217b892551465e5a44560a06e4b34dc3592b49622egdaniel 1323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (can_copy_image(dst, src, this)) { 132417b892551465e5a44560a06e4b34dc3592b49622egdaniel this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint); 132517b892551465e5a44560a06e4b34dc3592b49622egdaniel return true; 132617b892551465e5a44560a06e4b34dc3592b49622egdaniel } 132717b892551465e5a44560a06e4b34dc3592b49622egdaniel 132817b892551465e5a44560a06e4b34dc3592b49622egdaniel if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) { 132917b892551465e5a44560a06e4b34dc3592b49622egdaniel this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint); 1330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (can_copy_as_draw(dst, src, this)) { 1334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); 1335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 134137798fbd82a7d064c5cc1516f120546a3408044begdanielbool GrVkGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const { 134237798fbd82a7d064c5cc1516f120546a3408044begdaniel // Currently we don't support msaa 134337798fbd82a7d064c5cc1516f120546a3408044begdaniel if (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1) { 134437798fbd82a7d064c5cc1516f120546a3408044begdaniel return false; 134537798fbd82a7d064c5cc1516f120546a3408044begdaniel } 134637798fbd82a7d064c5cc1516f120546a3408044begdaniel 134737798fbd82a7d064c5cc1516f120546a3408044begdaniel // This will support copying the dst as CopyImage since all of our surfaces require transferSrc 134837798fbd82a7d064c5cc1516f120546a3408044begdaniel // and transferDst usage flags in Vulkan. 134937798fbd82a7d064c5cc1516f120546a3408044begdaniel desc->fOrigin = src->origin(); 135037798fbd82a7d064c5cc1516f120546a3408044begdaniel desc->fConfig = src->config(); 135137798fbd82a7d064c5cc1516f120546a3408044begdaniel desc->fFlags = kNone_GrSurfaceFlags; 135237798fbd82a7d064c5cc1516f120546a3408044begdaniel return true; 135337798fbd82a7d064c5cc1516f120546a3408044begdaniel} 135437798fbd82a7d064c5cc1516f120546a3408044begdaniel 135528f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&, 135628f45b949acc746849100fbe112ee5280f0594c9cdalton int* effectiveSampleCnt, SkAutoTDeleteArray<SkPoint>*) { 135728f45b949acc746849100fbe112ee5280f0594c9cdalton // TODO: stub. 135828f45b949acc746849100fbe112ee5280f0594c9cdalton SkASSERT(!this->caps()->sampleLocationsSupport()); 135928f45b949acc746849100fbe112ee5280f0594c9cdalton *effectiveSampleCnt = rt->desc().fSampleCnt; 136028f45b949acc746849100fbe112ee5280f0594c9cdalton} 136128f45b949acc746849100fbe112ee5280f0594c9cdalton 1362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes, 1363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig readConfig, DrawPreference* drawPreference, 1364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel ReadPixelTempDrawInfo* tempDrawInfo) { 136588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel // These settings we will always want if a temp draw is performed. 136688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag; 136788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fTempSurfaceDesc.fWidth = width; 136888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fTempSurfaceDesc.fHeight = height; 136988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0; 137088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL. 137188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fUseExactScratch = false; 137288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel 137388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel // For now assume no swizzling, we may change that below. 137488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fSwizzle = GrSwizzle::RGBA(); 137588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel 137688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read 137788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel // from will be srcConfig and we will read readConfig pixels from it. 137888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel // Not that if we require a draw and return a non-renderable format for the temp surface the 137988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel // base class will fail for us. 138088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config(); 138188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel tempDrawInfo->fReadConfig = readConfig; 138288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel 13834583ec51d9ddc830eeb854db068235be96ce59c4egdaniel if (srcSurface->config() == readConfig) { 13844583ec51d9ddc830eeb854db068235be96ce59c4egdaniel return true; 1385164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1386164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 13874583ec51d9ddc830eeb854db068235be96ce59c4egdaniel if (this->vkCaps().isConfigRenderable(readConfig, false)) { 13884583ec51d9ddc830eeb854db068235be96ce59c4egdaniel ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); 13894583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; 13904583ec51d9ddc830eeb854db068235be96ce59c4egdaniel tempDrawInfo->fReadConfig = readConfig; 13914583ec51d9ddc830eeb854db068235be96ce59c4egdaniel return true; 1392164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1393164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 13944583ec51d9ddc830eeb854db068235be96ce59c4egdaniel return false; 1395164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface, 1398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int left, int top, int width, int height, 1399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig config, 1400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* buffer, 1401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t rowBytes) { 1402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat pixelFormat; 1403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { 1404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture()); 1408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!tgt) { 1409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1411164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Change layout of our target so it can be used as copy 1413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tgt->setImageLayout(this, 1414164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 141550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_ACCESS_TRANSFER_READ_BIT, 141650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 1417164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 14199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary GrVkTransferBuffer* transferBuffer = 1420e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, 1421e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton kXferGpuToCpu_GrBufferType, 1422397536cabe12a9936659870dd220c869789424bacdalton kStream_GrAccessPattern)); 1423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); 1425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkOffset3D offset = { 1426164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel left, 1427164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flipY ? surface->height() - top - height : top, 1428164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 0 1429164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel }; 1430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Copy the image to a buffer so we can map it to cpu memory 1432164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkBufferImageCopy region; 1433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(®ion, 0, sizeof(VkBufferImageCopy)); 1434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.bufferOffset = 0; 143588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below. 1436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images. 1437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 1438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.imageOffset = offset; 1439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; 1440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->copyImageToBuffer(this, 1442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tgt, 1443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1444164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel transferBuffer, 1445164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1, 1446164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel ®ion); 1447164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1448164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // make sure the copy to buffer has finished 1449164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel transferBuffer->addMemoryBarrier(this, 1450164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_ACCESS_TRANSFER_WRITE_BIT, 1451164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_ACCESS_HOST_READ_BIT, 1452164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_PIPELINE_STAGE_TRANSFER_BIT, 1453164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_PIPELINE_STAGE_HOST_BIT, 1454164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1455164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1456164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We need to submit the current command buffer to the Queue and make sure it finishes before 1457164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // we can copy the data out of the buffer. 1458164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel this->submitCommandBuffer(kForce_SyncQueue); 1459164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1460164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* mappedMemory = transferBuffer->map(); 1461164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 146288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel size_t tightRowBytes = GrBytesPerPixel(config) * width; 1463164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (flipY) { 146488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel const char* srcRow = reinterpret_cast<const char*>(mappedMemory); 146588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes; 146688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel for (int y = 0; y < height; y++) { 146788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel memcpy(dstRow, srcRow, tightRowBytes); 146888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel srcRow += tightRowBytes; 146988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel dstRow -= rowBytes; 147088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel } 147188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel } else { 147288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel if (tightRowBytes == rowBytes) { 147388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel memcpy(buffer, mappedMemory, rowBytes*height); 147488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel } else { 147588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel SkRectMemcpy(buffer, rowBytes, mappedMemory, tightRowBytes, tightRowBytes, height); 1476164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1477164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1478164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 147988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel transferBuffer->unmap(); 148088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel transferBuffer->unref(); 148188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel 1482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1483164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1484066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel 14859cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielvoid GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer, 14869cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel const GrVkRenderPass* renderPass, 14879cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel const VkClearValue* colorClear, 14889cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel GrVkRenderTarget* target, 14899cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel const SkIRect& bounds) { 14909cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel // Currently it is fine for us to always pass in 1 for the clear count even if no attachment 14919cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment 14929cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel // which is always at the first attachment. 14939cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, bounds, true); 1494066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel fCurrentCmdBuffer->executeCommands(this, buffer); 1495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->endRenderPass(this); 1496164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 14979cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel 1498