GrVkGpu.cpp revision 2af0f1b014b9aabb6119bf66fac20e4cd3a8279b
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" 20164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImage.h" 21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkIndexBuffer.h" 22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h" 23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h" 2422281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel#include "GrVkPipelineState.h" 25164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h" 26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h" 27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h" 28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h" 29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h" 30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h" 31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "SkConfig8888.h" 33900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth#include "SkMipMap.h" 34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h" 36fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h" 37164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X) 39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X) 40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X) 41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 42d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS 43d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( 44d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth VkDebugReportFlagsEXT flags, 45d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth VkDebugReportObjectTypeEXT objectType, 46d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth uint64_t object, 47d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth size_t location, 48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth int32_t messageCode, 49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth const char* pLayerPrefix, 50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth const char* pMessage, 51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth void* pUserData) { 52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { 57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } else { 59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage); 60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } 61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth return VK_FALSE; 62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth} 63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif 64d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth 65633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options, 66633b35657c964c32e7010b14bb2d396b4a764c52jvanverth GrContext* context) { 67dc0fcd41e75682a8bfd5e285d684461475226330bsalomon const GrVkBackendContext* vkBackendContext = 68dc0fcd41e75682a8bfd5e285d684461475226330bsalomon reinterpret_cast<const GrVkBackendContext*>(backendContext); 69633b35657c964c32e7010b14bb2d396b4a764c52jvanverth if (!vkBackendContext) { 70dc0fcd41e75682a8bfd5e285d684461475226330bsalomon vkBackendContext = GrVkBackendContext::Create(); 71633b35657c964c32e7010b14bb2d396b4a764c52jvanverth if (!vkBackendContext) { 72633b35657c964c32e7010b14bb2d396b4a764c52jvanverth return nullptr; 73164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 74633b35657c964c32e7010b14bb2d396b4a764c52jvanverth } else { 75633b35657c964c32e7010b14bb2d396b4a764c52jvanverth vkBackendContext->ref(); 76164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 77164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 78633b35657c964c32e7010b14bb2d396b4a764c52jvanverth return new GrVkGpu(context, options, vkBackendContext); 79164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 839d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options, 84633b35657c964c32e7010b14bb2d396b4a764c52jvanverth const GrVkBackendContext* backendCtx) 85164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel : INHERITED(context) 86633b35657c964c32e7010b14bb2d396b4a764c52jvanverth , fDevice(backendCtx->fDevice) 87633b35657c964c32e7010b14bb2d396b4a764c52jvanverth , fQueue(backendCtx->fQueue) 88633b35657c964c32e7010b14bb2d396b4a764c52jvanverth , fResourceProvider(this) { 89633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fBackendContext.reset(backendCtx); 90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 91d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS 92a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth fCallback = nullptr; 93fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) { 94fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth // Setup callback creation information 95d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth VkDebugReportCallbackCreateInfoEXT callbackCreateInfo; 96d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 97d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.pNext = nullptr; 98d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 99ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel VK_DEBUG_REPORT_WARNING_BIT_EXT | 100d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth //VK_DEBUG_REPORT_INFORMATION_BIT_EXT | 101d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth //VK_DEBUG_REPORT_DEBUG_BIT_EXT | 102b4aa36211ca66ef127ac2954108742af1ead5082egdaniel VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 103d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.pfnCallback = &DebugReportCallback; 104d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth callbackCreateInfo.pUserData = nullptr; 105d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth 106fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth // Register the callback 107a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT( 108a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback)); 109d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth } 110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif 111633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 112633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCompiler = shaderc_compiler_initialize(); 113633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 114fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice, 115c5ec1408298510410270ea67e895570ccfa76e54egdaniel backendCtx->fFeatures, backendCtx->fExtensions)); 116633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCaps.reset(SkRef(fVkCaps.get())); 117633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 118633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps)); 119633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 120633b35657c964c32e7010b14bb2d396b4a764c52jvanverth const VkCommandPoolCreateInfo cmdPoolInfo = { 121633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType 122633b35657c964c32e7010b14bb2d396b4a764c52jvanverth nullptr, // pNext 123633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // CmdPoolCreateFlags 124b0d4352ca610654f98c3c4ebc67ed9ad9c8c8493jvanverth backendCtx->fGraphicsQueueIndex, // queueFamilyIndex 125633b35657c964c32e7010b14bb2d396b4a764c52jvanverth }; 1269d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr, 127633b35657c964c32e7010b14bb2d396b4a764c52jvanverth &fCmdPool)); 128633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth // must call this after creating the CommandPool 130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fResourceProvider.init(); 131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCurrentCmdBuffer = fResourceProvider.createCommandBuffer(); 132633b35657c964c32e7010b14bb2d396b4a764c52jvanverth SkASSERT(fCurrentCmdBuffer); 133633b35657c964c32e7010b14bb2d396b4a764c52jvanverth fCurrentCmdBuffer->begin(this); 134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() { 137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->end(this); 138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->unref(this); 139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // wait for all commands to finish 141ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth fResourceProvider.checkCommandBuffers(); 142a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth SkDEBUGCODE(VkResult res = ) VK_CALL(QueueWaitIdle(fQueue)); 143ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth // VK_ERROR_DEVICE_LOST is acceptable when tearing down (see 4.2.4 in spec) 144ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res); 1459d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // must call this just before we destroy the VkDevice 147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fResourceProvider.destroyResources(); 148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 149633b35657c964c32e7010b14bb2d396b4a764c52jvanverth VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr)); 150633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 151633b35657c964c32e7010b14bb2d396b4a764c52jvanverth shaderc_compiler_release(fCompiler); 152633b35657c964c32e7010b14bb2d396b4a764c52jvanverth 153633b35657c964c32e7010b14bb2d396b4a764c52jvanverth#ifdef ENABLE_VK_LAYERS 154a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth if (fCallback) { 155a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr)); 156a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth fCallback = nullptr; 157a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth } 158d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif 159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/////////////////////////////////////////////////////////////////////////////// 162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) { 164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->end(this); 166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->submitToQueue(this, fQueue, sync); 168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fResourceProvider.checkCommandBuffers(); 169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Release old command buffer and create a new one 171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->unref(this); 172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer = fResourceProvider.createCommandBuffer(); 173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->begin(this); 176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/////////////////////////////////////////////////////////////////////////////// 1791bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern, 1801bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton const void* data) { 1811bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton GrBuffer* buff; 182397536cabe12a9936659870dd220c869789424bacdalton switch (type) { 183397536cabe12a9936659870dd220c869789424bacdalton case kVertex_GrBufferType: 184397536cabe12a9936659870dd220c869789424bacdalton SkASSERT(kDynamic_GrAccessPattern == accessPattern || 185397536cabe12a9936659870dd220c869789424bacdalton kStatic_GrAccessPattern == accessPattern); 1861bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); 187e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 188397536cabe12a9936659870dd220c869789424bacdalton case kIndex_GrBufferType: 189397536cabe12a9936659870dd220c869789424bacdalton SkASSERT(kDynamic_GrAccessPattern == accessPattern || 190397536cabe12a9936659870dd220c869789424bacdalton kStatic_GrAccessPattern == accessPattern); 1911bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); 192e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 193397536cabe12a9936659870dd220c869789424bacdalton case kXferCpuToGpu_GrBufferType: 194c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth SkASSERT(kStream_GrAccessPattern == accessPattern); 1951bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type); 196e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 197397536cabe12a9936659870dd220c869789424bacdalton case kXferGpuToCpu_GrBufferType: 198c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth SkASSERT(kStream_GrAccessPattern == accessPattern); 1991bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type); 200e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel break; 201397536cabe12a9936659870dd220c869789424bacdalton default: 202397536cabe12a9936659870dd220c869789424bacdalton SkFAIL("Unknown buffer type."); 203397536cabe12a9936659870dd220c869789424bacdalton return nullptr; 204397536cabe12a9936659870dd220c869789424bacdalton } 2051bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton if (data && buff) { 2061bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton buff->updateData(data, size); 2071bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton } 2081bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton return buff; 209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, 213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig srcConfig, DrawPreference* drawPreference, 214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel WritePixelTempDrawInfo* tempDrawInfo) { 215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) { 216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail 220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kNoDraw_DrawPreference != *drawPreference) { 221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (dstSurface->config() != srcConfig) { 2259d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary // TODO: This should fall back to drawing or copying to change config of dstSurface to 226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // match that of srcConfig. 227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface, 234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int left, int top, int width, int height, 235a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon GrPixelConfig config, 236a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon const SkTArray<GrMipLevel>& texels) { 237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture()); 238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!vkTex) { 239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 242900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Make sure we have at least the base level 24303509eafa3e25819ff69f4d4f339d46264820c38jvanverth if (texels.empty() || !texels.begin()->fPixels) { 24403509eafa3e25819ff69f4d4f339d46264820c38jvanverth return false; 24503509eafa3e25819ff69f4d4f339d46264820c38jvanverth } 246a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon 247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels. 248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { 249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool success = false; 253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) { 254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo() 255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(config == vkTex->desc().fConfig); 256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: add compressed texture support 257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // delete the following two lines and uncomment the two after that when ready 258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel vkTex->unref(); 259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width, 261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // height); 262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool linearTiling = vkTex->isLinearTiled(); 264900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (linearTiling) { 265900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (texels.count() > 1) { 266900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkDebugf("Can't upload mipmap data to linear tiled texture"); 267900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 268900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 269900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) { 270900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Need to change the layout to general in order to perform a host write 271900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkImageLayout layout = vkTex->currentLayout(); 272900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); 273900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_HOST_BIT; 274900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); 275900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkAccessFlags dstAccessMask = VK_ACCESS_HOST_WRITE_BIT; 276900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth vkTex->setImageLayout(this, 277900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_GENERAL, 278900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcAccessMask, 279900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dstAccessMask, 280900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcStageMask, 281900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dstStageMask, 282900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth false); 283bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel this->submitCommandBuffer(kForce_SyncQueue); 284900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 285900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataLinear(vkTex, left, top, width, height, config, 286900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth texels.begin()->fPixels, texels.begin()->fRowBytes); 287900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else { 288c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int newMipLevels = texels.count(); 289c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int currentMipLevels = vkTex->texturePriv().maxMipMapLevel(); 290c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if ((currentMipLevels || newMipLevels != 1) && newMipLevels != currentMipLevels) { 291c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if (!vkTex->reallocForMipmap(this, newMipLevels)) { 292900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 293900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 294900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 295900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels); 296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 298900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 299900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return success; 300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 302900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, 303900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth int left, int top, int width, int height, 304900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrPixelConfig dataConfig, 305900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const void* data, 306900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth size_t rowBytes) { 307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(data); 308900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(tex->isLinearTiled()); 309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // If we're uploading compressed data then we should be using uploadCompressedTexData 311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); 312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t bpp = GrBytesPerPixel(dataConfig); 314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrSurfaceDesc& desc = tex->desc(); 316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, 318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel &width, &height, &data, &rowBytes)) { 319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t trimRowBytes = width * bpp; 322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 323900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() || 324900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout()); 325900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const VkImageSubresource subres = { 326900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_ASPECT_COLOR_BIT, 327900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 0, // mipLevel 328900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 0, // arraySlice 329900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth }; 330900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkSubresourceLayout layout; 331900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkResult err; 332900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 333900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const GrVkInterface* interface = this->vkInterface(); 334900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 335900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice, 336900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth tex->textureImage(), 337900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth &subres, 338900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth &layout)); 339900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 340900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top; 341900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkDeviceSize offset = texTop*layout.rowPitch + left*bpp; 342900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkDeviceSize size = height*layout.rowPitch; 343900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth void* mapPtr; 344900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth err = GR_VK_CALL(interface, MapMemory(fDevice, tex->textureMemory(), offset, size, 0, 345900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth &mapPtr)); 346900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (err) { 347900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 348900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 350900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { 351900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // copy into buffer by rows 352900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const char* srcRow = reinterpret_cast<const char*>(data); 353900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch; 354900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth for (int y = 0; y < height; y++) { 355900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(dstRow, srcRow, trimRowBytes); 356900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcRow += rowBytes; 357900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dstRow -= layout.rowPitch; 358900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 359900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else { 360900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy 361900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) { 362900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(mapPtr, data, trimRowBytes * height); 363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 364900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, 365900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth trimRowBytes, height); 366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 367900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 369900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GR_VK_CALL(interface, UnmapMemory(fDevice, tex->textureMemory())); 370900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 371900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return true; 372900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth} 373900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 374900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, 375900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth int left, int top, int width, int height, 376900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrPixelConfig dataConfig, 377900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const SkTArray<GrMipLevel>& texels) { 378900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(!tex->isLinearTiled()); 379900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // The assumption is either that we have no mipmaps, or that our rect is the entire texture 380900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(1 == texels.count() || 381900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth (0 == left && 0 == top && width == tex->width() && height == tex->height())); 382900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 383900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // If we're uploading compressed data then we should be using uploadCompressedTexData 384900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); 385900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 386900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (width == 0 || height == 0) { 387900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return false; 388900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 389900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 390900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const GrSurfaceDesc& desc = tex->desc(); 391900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); 392900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth size_t bpp = GrBytesPerPixel(dataConfig); 393900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 394900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // texels is const. 395c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes. 396c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // Because of this we need to make a non-const shallow copy of texels. 397c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkTArray<GrMipLevel> texelsShallowCopy(texels); 398900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 399c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0; 400c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentMipLevel--) { 401c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkASSERT(texelsShallowCopy[currentMipLevel].fPixels); 402900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 403900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 404900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Determine whether we need to flip when we copy into the buffer 405c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty()); 406900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 407c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // adjust any params (left, top, currentWidth, currentHeight 408900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // find the combined size of all the mip levels and the relative offset of 409900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // each into the collective buffer 410c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // Do the first level separately because we may need to adjust width and height 411c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth // (for the non-mipped case). 412c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, 413c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &width, 414c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &height, 415c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[0].fPixels, 416c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[0].fRowBytes)) { 417c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth return false; 418c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth } 419c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count()); 420c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth individualMipOffsets.push_back(0); 421c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth size_t combinedBufferSize = width * bpp * height; 422c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int currentWidth = width; 423c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int currentHeight = height; 424c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) { 425c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentWidth = SkTMax(1, currentWidth/2); 426c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentHeight = SkTMax(1, currentHeight/2); 427c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, 428c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth ¤tWidth, 429c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth ¤tHeight, 430c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[currentMipLevel].fPixels, 431c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth &texelsShallowCopy[currentMipLevel].fRowBytes)) { 432c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth return false; 433c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth } 434900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const size_t trimmedSize = currentWidth * bpp * currentHeight; 435900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth individualMipOffsets.push_back(combinedBufferSize); 436900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth combinedBufferSize += trimmedSize; 437900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 438900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 439900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // allocate buffer to hold our mip data 440900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrVkTransferBuffer* transferBuffer = 441900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type); 442900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 443900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth char* buffer = (char*) transferBuffer->map(); 444c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count()); 445900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 446c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentWidth = width; 447c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentHeight = height; 448c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) { 449900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth const size_t trimRowBytes = currentWidth * bpp; 450c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; 451900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 452900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // copy data into the buffer, skipping the trailing bytes 453900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth char* dst = buffer + individualMipOffsets[currentMipLevel]; 454c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels; 455900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (flipY) { 456900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth src += (currentHeight - 1) * rowBytes; 457900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth for (int y = 0; y < currentHeight; y++) { 458900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(dst, src, trimRowBytes); 459900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth src -= rowBytes; 460900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dst += trimRowBytes; 461164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 462900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else if (trimRowBytes == rowBytes) { 463900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth memcpy(dst, src, trimRowBytes * currentHeight); 464164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 465900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight); 466164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 467164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 468900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkBufferImageCopy& region = regions.push_back(); 469164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(®ion, 0, sizeof(VkBufferImageCopy)); 470900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.bufferOffset = individualMipOffsets[currentMipLevel]; 471900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.bufferRowLength = currentWidth; 472900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.bufferImageHeight = currentHeight; 473cf942c4ef750712b624867cbb2217c14857db3c6bsalomon region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 }; 474c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 }; 475900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 }; 476c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth 477c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentWidth = SkTMax(1, currentWidth/2); 478c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth currentHeight = SkTMax(1, currentHeight/2); 479900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 480164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 481900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer->unmap(); 482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 483900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // make sure the unmap has finished 484900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer->addMemoryBarrier(this, 485900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_ACCESS_HOST_WRITE_BIT, 486900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_ACCESS_TRANSFER_READ_BIT, 487900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 488900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_PIPELINE_STAGE_TRANSFER_BIT, 489900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth false); 490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 491900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Change layout of our target so it can be copied to 492900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkImageLayout layout = tex->currentLayout(); 493900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); 494900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 495900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); 496900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 497900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth tex->setImageLayout(this, 498900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 499900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcAccessMask, 500900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dstAccessMask, 501900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcStageMask, 502900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth dstStageMask, 503900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth false); 504900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 505900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Copy the buffer to the image 506900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth fCurrentCmdBuffer->copyBufferToImage(this, 507900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer, 508900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth tex, 509900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 510900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth regions.count(), 511900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth regions.begin()); 512900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // Submit the current command buffer to the Queue 514900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth this->submitCommandBuffer(kSkip_SyncQueue); 515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 516900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth transferBuffer->unref(); 517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 518164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 5222e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, 523a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon const SkTArray<GrMipLevel>& texels) { 524164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); 525164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 526164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat pixelFormat; 527164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) { 528164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 530164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!fVkCaps->isConfigTexturable(desc.fConfig)) { 532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 534164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool linearTiling = false; 536164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) { 537900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // we can't have a linear texture with a mipmap 538900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (texels.count() > 1) { 539900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkDebugf("Trying to create linear tiled texture with mipmap"); 540900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth return nullptr; 541900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 542164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (fVkCaps->isConfigTexurableLinearly(desc.fConfig) && 543164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) { 544164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel linearTiling = true; 545164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 546164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 547164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 548164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 549164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 550164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; 551164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (renderTarget) { 552164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 553164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 555164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and 556164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we 557164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // will be using this texture in some copy or not. Also this assumes, as is the current case, 55862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // that all render targets in vulkan are also textures. If we change this practice of setting 559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // both bits, we must make sure to set the destination bit if we are uploading srcData to the 560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // texture. 561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 563a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : 564a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is 56762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set 568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // to 1. 569c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth int mipLevels = texels.empty() ? 1 : texels.count(); 570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkImage::ImageDesc imageDesc; 571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fImageType = VK_IMAGE_TYPE_2D; 572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fFormat = pixelFormat; 573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fWidth = desc.fWidth; 574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fHeight = desc.fHeight; 575c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth imageDesc.fLevels = linearTiling ? 1 : mipLevels; 576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fSamples = 1; 577164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; 578164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fUsageFlags = usageFlags; 579164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc.fMemProps = memProps; 580164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* tex; 582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (renderTarget) { 5832e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc, 584164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel imageDesc); 585164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 5862e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc); 587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!tex) { 590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 593e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon if (!texels.empty()) { 594e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon SkASSERT(texels.begin()->fPixels); 595900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth bool success; 596900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (linearTiling) { 597900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, 598900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth texels.begin()->fPixels, texels.begin()->fRowBytes); 599900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } else { 600900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, 601900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth texels); 602900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth } 603900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (!success) { 604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tex->unref(); 605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 609164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return tex; 610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 613164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) { 615164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // By default, all textures in Vk use TopLeft 616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kDefault_GrSurfaceOrigin == origin) { 617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return kTopLeft_GrSurfaceOrigin; 618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return origin; 620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 621164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, 624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrWrapOwnership ownership) { 625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat format; 626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) { 627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (0 == desc.fTextureHandle) { 631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int maxSize = this->caps()->maxTextureSize(); 635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (desc.fWidth > maxSize || desc.fHeight > maxSize) { 636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 639fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth const GrVkTextureInfo* info = reinterpret_cast<const GrVkTextureInfo*>(desc.fTextureHandle); 640fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc) { 641fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return nullptr; 642fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth } 643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurfaceDesc surfDesc; 645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // next line relies on GrBackendTextureDesc's flags matching GrTexture's 646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags; 647164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fWidth = desc.fWidth; 648164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fHeight = desc.fHeight; 649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fConfig = desc.fConfig; 650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()); 651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag); 652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // In GL, Chrome assumes all textures are BottomLeft 653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // In VK, we don't have this restriction 654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel surfDesc.fOrigin = resolve_origin(desc.fOrigin); 655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* texture = nullptr; 657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (renderTarget) { 6589d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc, 6592e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen ownership, format, 660fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info); 661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 6622e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, format, info); 663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!texture) { 665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return texture; 669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc, 672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrWrapOwnership ownership) { 6739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 674fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth const GrVkTextureInfo* info = 675fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth reinterpret_cast<const GrVkTextureInfo*>(wrapDesc.fRenderTargetHandle); 676fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth if (VK_NULL_HANDLE == info->fImage || 677fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth (VK_NULL_HANDLE == info->fAlloc && kAdopt_GrWrapOwnership == ownership)) { 678fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return nullptr; 679fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth } 680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurfaceDesc desc; 682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fConfig = wrapDesc.fConfig; 683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fFlags = kCheckAllocation_GrSurfaceFlag; 684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fWidth = wrapDesc.fWidth; 685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fHeight = wrapDesc.fHeight; 686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount()); 687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel desc.fOrigin = resolve_origin(wrapDesc.fOrigin); 689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc, 6912e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen ownership, 692fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info); 693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (tgt && wrapDesc.fStencilBits) { 694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) { 695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tgt->unref(); 696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return nullptr; 697164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 699164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return tgt; 700164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 70262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverthvoid GrVkGpu::generateMipmap(GrVkTexture* tex) const { 703900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // don't do anything for linearly tiled textures (can't have mipmaps) 70462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth if (tex->isLinearTiled()) { 705900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkDebugf("Trying to create mipmap for linear tiled texture"); 70662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 70762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 70862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 70962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // We cannot generate mipmaps for images that are multisampled. 71062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // TODO: does it even make sense for rendertargets in general? 71162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth if (tex->asRenderTarget() && tex->asRenderTarget()->numColorSamples() > 1) { 71262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 71362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 71462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 71562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // determine if we can blit to and from this format 71662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth const GrVkCaps& caps = this->vkCaps(); 71762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth if (!caps.configCanBeDstofBlit(tex->config(), false) || 71862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth !caps.configCanBeSrcofBlit(tex->config(), false)) { 71962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 72062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 72162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 72262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // change the original image's layout 72362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkImageLayout origSrcLayout = tex->currentLayout(); 72462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout); 72562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 72662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 72762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout); 72862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 72962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 73062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 73162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, false); 73262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 73362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // grab handle to the original image resource 73462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth const GrVkImage::Resource* oldResource = tex->resource(); 73562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource->ref(); 73662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 737900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth uint32_t mipLevels = SkMipMap::ComputeLevelCount(tex->width(), tex->height()); 738900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth if (!tex->reallocForMipmap(this, mipLevels)) { 73962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource->unref(this); 74062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth return; 74162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 74262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 74362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // change the new image's layout 74462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkImageLayout origDstLayout = tex->currentLayout(); 74562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 74662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 74762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 74862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 74962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); 75062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 75162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 7522af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 7532af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, false); 75462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 75562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // Blit original image 75662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth int width = tex->width(); 75762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth int height = tex->height(); 75862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth uint32_t mipLevel = 0; 75962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 76062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VkImageBlit blitRegion; 76162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth memset(&blitRegion, 0, sizeof(VkImageBlit)); 76262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 76362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcOffsets[0] = { 0, 0, 0 }; 76462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcOffsets[1] = { width, height, 0 }; 76562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 }; 76662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstOffsets[0] = { 0, 0, 0 }; 76762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstOffsets[1] = { width, height, 0 }; 76862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 76962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth fCurrentCmdBuffer->blitImage(this, 77062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource, 77162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 77262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth tex->resource(), 77362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 77462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 1, 77562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth &blitRegion, 77662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_FILTER_LINEAR); 77762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth // Blit the miplevels 77862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth while (width/2 > 0 && height/2 > 0) { 77962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 }; 78062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcOffsets[0] = { 0, 0, 0 }; 78162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.srcOffsets[1] = { width, height, 0 }; 78262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel+1, 0, 1 }; 78362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstOffsets[0] = { 0, 0, 0 }; 78462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth blitRegion.dstOffsets[1] = { width/2, height/2, 0 }; 78562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 786900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth // TODO: insert image barrier to wait on previous blit 7872af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth // TODO: change layout of src subresource to TRANSFER_SRC_OPTIMAL 788900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 78962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth fCurrentCmdBuffer->blitImage(this, 79062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth tex->resource(), 79162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 79262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth tex->resource(), 79362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 79462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 1, 79562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth &blitRegion, 79662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth VK_FILTER_LINEAR); 79762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 79862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth width /= 2; 79962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth height /= 2; 80062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth mipLevel++; 80162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth } 80262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 80362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth oldResource->unref(this); 80462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth} 80562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 80662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 80762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth 808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc, 8110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrNonInstancedMesh& mesh) { 81258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // There is no need to put any memory barriers to make sure host writes have finished here. 81358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // When a command buffer is submitted to a queue, there is an implicit memory barrier that 81458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of 81558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // an active RenderPass. 816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkVertexBuffer* vbuf; 8170e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer(); 818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(vbuf); 819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(!vbuf->isMapped()); 820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->bindVertexBuffer(this, vbuf); 822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 8230e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel if (mesh.isIndexed()) { 8240e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer(); 825164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(ibuf); 826164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(!ibuf->isMapped()); 827164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 828164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->bindIndexBuffer(this, ibuf); 829164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 830164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 831164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 834164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt, 835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int width, 836164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int height) { 837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(width >= rt->width()); 838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(height >= rt->height()); 839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 840164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int samples = rt->numStencilSamples(); 841164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 8428f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat(); 843164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 844164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this, 845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel width, 846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel height, 847164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel samples, 848164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel sFmt)); 849164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fStats.incStencilAttachmentCreates(); 850164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return stencil; 851164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 852164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 853164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 854164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 855164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h, 856164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig config) { 857164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 858164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat pixelFormat; 859164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { 860164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 861164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 862164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 863164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool linearTiling = false; 864164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!fVkCaps->isConfigTexturable(config)) { 865164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 866164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 867164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 868164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (fVkCaps->isConfigTexurableLinearly(config)) { 869164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel linearTiling = true; 870164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 871164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 872164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Currently this is not supported since it requires a copy which has not yet been implemented. 873164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (srcData && !linearTiling) { 874164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 875164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 876164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 877164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; 878164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 879164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; 880164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 881164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : 882164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 883164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 884fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkImage image = VK_NULL_HANDLE; 885fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkDeviceMemory alloc = VK_NULL_HANDLE; 886164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 887fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; 888fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling) 889fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth ? VK_IMAGE_LAYOUT_PREINITIALIZED 890fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth : VK_IMAGE_LAYOUT_UNDEFINED; 891fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 892fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth // Create Image 893fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VkSampleCountFlagBits vkSamples; 894fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth if (!GrSampleCountToVkSampleCount(1, &vkSamples)) { 895fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return 0; 896fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth } 897fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 898fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth const VkImageCreateInfo imageCreateInfo = { 899fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType 900fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth NULL, // pNext 901fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 0, // VkImageCreateFlags 902fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_IMAGE_TYPE_2D, // VkImageType 903fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth pixelFormat, // VkFormat 904384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas { (uint32_t) w, (uint32_t) h, 1 }, // VkExtent3D 905fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 1, // mipLevels 906fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 1, // arrayLayers 907fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth vkSamples, // samples 908fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth imageTiling, // VkImageTiling 909fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth usageFlags, // VkImageUsageFlags 910fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode 911fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 0, // queueFamilyCount 912fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 0, // pQueueFamilyIndices 913fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth initialLayout // initialLayout 914fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth }; 915fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 916fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image)); 917fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 918fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth if (!GrVkMemory::AllocAndBindImageMemory(this, image, memProps, &alloc)) { 919fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(DestroyImage(this->device(), image, nullptr)); 920164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 921164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 922164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 923164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (srcData) { 924164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (linearTiling) { 925164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const VkImageSubresource subres = { 926164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_ASPECT_COLOR_BIT, 927164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 0, // mipLevel 928164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 0, // arraySlice 929164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel }; 930164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkSubresourceLayout layout; 931164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkResult err; 932164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 933fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout)); 934164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 935164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* mapPtr; 936fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth err = VK_CALL(MapMemory(fDevice, alloc, 0, layout.rowPitch * h, 0, &mapPtr)); 937164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (err) { 938fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(FreeMemory(this->device(), alloc, nullptr)); 939fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(DestroyImage(this->device(), image, nullptr)); 940164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return 0; 941164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 942164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 943164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t bpp = GrBytesPerPixel(config); 944164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t rowCopyBytes = bpp * w; 945164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // If there is no padding on dst (layout.rowPitch) we can do a single memcopy. 946164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // This assumes the srcData comes in with no padding. 947164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (rowCopyBytes == layout.rowPitch) { 948164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memcpy(mapPtr, srcData, rowCopyBytes * h); 949164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 950fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcData, rowCopyBytes, 951fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth rowCopyBytes, h); 952164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 953fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(UnmapMemory(fDevice, alloc)); 954164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else { 955164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: Add support for copying to optimal tiling 956164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(false); 957164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 958164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 959164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 960fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth GrVkTextureInfo* info = new GrVkTextureInfo; 961fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fImage = image; 962fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fAlloc = alloc; 963fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fImageTiling = imageTiling; 964fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth info->fImageLayout = initialLayout; 96558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel info->fFormat = pixelFormat; 9662af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth info->fLevelCount = 1; 967fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 968fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth return (GrBackendObject)info; 969164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 970164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 971164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const { 972fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id); 973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (backend && backend->fImage && backend->fAlloc) { 975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkMemoryRequirements req; 976164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(&req, 0, sizeof(req)); 977164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice, 978164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel backend->fImage, 979164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel &req)); 980164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: find a better check 981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // This will probably fail with a different driver 982164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return (req.size > 0) && (req.size <= 8192 * 8192); 983164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 985164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 986164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) { 989fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id); 990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (backend) { 992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!abandon) { 993fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth // something in the command buffer may still be using this, so force submit 994fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth this->submitCommandBuffer(kForce_SyncQueue); 995fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth 996fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(FreeMemory(this->device(), backend->fAlloc, nullptr)); 997fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth VK_CALL(DestroyImage(this->device(), backend->fImage, nullptr)); 998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 999fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth delete backend; 1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1003164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel//////////////////////////////////////////////////////////////////////////////// 1004164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1005164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask, 1006164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask, 1007164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool byRegion, 1008164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkMemoryBarrier* barrier) const { 1009164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 1010164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->pipelineBarrier(this, 1011164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel byRegion, 1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkCommandBuffer::kMemory_BarrierType, 1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel barrier); 1016164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1018164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask, 1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask, 1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool byRegion, 1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkBufferMemoryBarrier* barrier) const { 1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->pipelineBarrier(this, 1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel byRegion, 1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkCommandBuffer::kBufferMemory_BarrierType, 1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel barrier); 1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask, 1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask, 1033164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool byRegion, 1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageMemoryBarrier* barrier) const { 1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(fCurrentCmdBuffer); 1036164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->pipelineBarrier(this, 1037164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1038164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel byRegion, 1040164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkCommandBuffer::kImageMemory_BarrierType, 1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel barrier); 1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() { 1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Submit the current command buffer to the Queue 1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel this->submitCommandBuffer(kSkip_SyncQueue); 1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 10493d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) { 10503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel if (nullptr == target) { 10513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel return; 10523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } 10533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment(); 10543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; 10553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkClearDepthStencilValue vkStencilColor; 10583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); 10593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkImageLayout origDstLayout = vkStencil->currentLayout(); 10613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 10633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 10643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);; 10663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 10673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkStencil->setImageLayout(this, 10693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 10703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel srcAccessMask, 10713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel dstAccessMask, 10723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel srcStageMask, 10733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel dstStageMask, 10743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel false); 10753d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10763d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10773d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkImageSubresourceRange subRange; 10783d5d9ac426ea926f37eaa47e13acf7492068667begdaniel memset(&subRange, 0, sizeof(VkImageSubresourceRange)); 10793d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; 10803d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.baseMipLevel = 0; 10813d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.levelCount = 1; 10823d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.baseArrayLayer = 0; 10833d5d9ac426ea926f37eaa47e13acf7492068667begdaniel subRange.layerCount = 1; 10843d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10853d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a 10863d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // draw. Thus we should look into using the load op functions on the render pass to clear out 10873d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // the stencil there. 10883d5d9ac426ea926f37eaa47e13acf7492068667begdaniel fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange); 10893d5d9ac426ea926f37eaa47e13acf7492068667begdaniel} 10903d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10913d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) { 10923d5d9ac426ea926f37eaa47e13acf7492068667begdaniel SkASSERT(target); 10933d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10943d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); 10953d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment(); 10963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb; 10973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 10983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // this should only be called internally when we know we have a 10993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // stencil buffer. 11003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel SkASSERT(sb); 11013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel int stencilBitCount = sb->bits(); 11023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11033d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // The contract with the callers does not guarantee that we preserve all bits in the stencil 11043d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // during this clear. Thus we will clear the entire stencil to the desired value. 11053d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11063d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkClearDepthStencilValue vkStencilColor; 11073d5d9ac426ea926f37eaa47e13acf7492068667begdaniel memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); 11083d5d9ac426ea926f37eaa47e13acf7492068667begdaniel if (insideClip) { 11093d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkStencilColor.stencil = (1 << (stencilBitCount - 1)); 11103d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } else { 11113d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkStencilColor.stencil = 0; 11123d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } 11133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkImageLayout origDstLayout = vkStencil->currentLayout(); 11153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); 11163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 111758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 11183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 11193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkStencil->setImageLayout(this, 11203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 11213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel srcAccessMask, 11223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel dstAccessMask, 11233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel srcStageMask, 11243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel dstStageMask, 11253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel false); 11263d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 112758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // Change layout of our render target so it can be used as the color attachment. This is what 112858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // the render pass expects when it begins. 112958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel VkImageLayout layout = vkRT->currentLayout(); 113058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); 113158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 113258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); 113358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 113458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel vkRT->setImageLayout(this, 113558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 113658a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcAccessMask, 113758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstAccessMask, 113858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcStageMask, 113958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstStageMask, 114058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel false); 114158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel 11423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkClearRect clearRect; 11433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // Flip rect if necessary 11443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel SkIRect vkRect = rect; 11453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { 11473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkRect.fTop = vkRT->height() - rect.fBottom; 11483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkRect.fBottom = vkRT->height() - rect.fTop; 11493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } 11503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; 11523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; 11533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel clearRect.baseArrayLayer = 0; 11553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel clearRect.layerCount = 1; 11563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); 11583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel SkASSERT(renderPass); 11593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); 11603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel uint32_t stencilIndex; 11623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex)); 11633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkClearAttachment attachment; 11653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; 11663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel attachment.colorAttachment = 0; // this value shouldn't matter 11673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel attachment.clearValue.depthStencil = vkStencilColor; 11683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect); 11703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel fCurrentCmdBuffer->endRenderPass(this); 11713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 11723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel return; 11733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel} 11743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 1175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) { 1176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // parent class should never let us get here with no RT 1177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(target); 1178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkClearColorValue vkColor; 1180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrColorToRGBAFloat(color, vkColor.float32); 11819d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 1182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); 1183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageLayout origDstLayout = vkRT->currentLayout(); 1184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (rect.width() != target->width() || rect.height() != target->height()) { 1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); 1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 118858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 1190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel vkRT->setImageLayout(this, 1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcAccessMask, 1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstAccessMask, 1194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 119858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // If we are using a stencil attachment we also need to change its layout to what the render 119958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel // pass is expecting. 120058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) { 120158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; 120258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel origDstLayout = vkStencil->currentLayout(); 120358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); 120458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 120558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; 120658a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 120758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 120858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel vkStencil->setImageLayout(this, 120958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 121058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcAccessMask, 121158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstAccessMask, 121258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel srcStageMask, 121358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel dstStageMask, 121458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel false); 121558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel } 121658a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel 1217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkClearRect clearRect; 12183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // Flip rect if necessary 12193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel SkIRect vkRect = rect; 12203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { 12213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkRect.fTop = vkRT->height() - rect.fBottom; 12223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkRect.fBottom = vkRT->height() - rect.fTop; 12233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } 12243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; 12253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; 1226e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth clearRect.baseArrayLayer = 0; 1227e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth clearRect.layerCount = 1; 1228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); 1230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(renderPass); 1231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); 1232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel uint32_t colorIndex; 1234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex)); 1235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkClearAttachment attachment; 1237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel attachment.colorAttachment = colorIndex; 1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel attachment.clearValue.color = vkColor; 1240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect); 1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->endRenderPass(this); 1243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return; 1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);; 1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel vkRT->setImageLayout(this, 1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcAccessMask, 1255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstAccessMask, 1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageSubresourceRange subRange; 1262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(&subRange, 0, sizeof(VkImageSubresourceRange)); 1263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel subRange.baseMipLevel = 0; 1265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel subRange.levelCount = 1; 1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel subRange.baseArrayLayer = 0; 1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel subRange.layerCount = 1; 1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 12699d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary // In the future we may not actually be doing this type of clear at all. If we are inside a 1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more 1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // common use case will be clearing an attachment at the start of a render pass, in which case 1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // we will use the clear load ops. 1273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->clearColorImage(this, 1274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel vkRT, 1275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel &vkColor, 1276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1, &subRange); 1277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst, 1280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrSurface* src, 1281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrVkGpu* gpu) { 128217b892551465e5a44560a06e4b34dc3592b49622egdaniel // Currently we don't support msaa 128317b892551465e5a44560a06e4b34dc3592b49622egdaniel if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) || 128417b892551465e5a44560a06e4b34dc3592b49622egdaniel (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) { 128517b892551465e5a44560a06e4b34dc3592b49622egdaniel return false; 128617b892551465e5a44560a06e4b34dc3592b49622egdaniel } 128717b892551465e5a44560a06e4b34dc3592b49622egdaniel 128817b892551465e5a44560a06e4b34dc3592b49622egdaniel // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src 128917b892551465e5a44560a06e4b34dc3592b49622egdaniel // as image usage flags. 129017b892551465e5a44560a06e4b34dc3592b49622egdaniel if (src->origin() == dst->origin() && 129117b892551465e5a44560a06e4b34dc3592b49622egdaniel GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) { 1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled 129617b892551465e5a44560a06e4b34dc3592b49622egdaniel // or the resolved image here? Im multisampled, Vulkan requires sample counts to be the same. 1297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, 1302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurface* src, 130317b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* dstImage, 130417b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* srcImage, 1305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIRect& srcRect, 1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIPoint& dstPoint) { 1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(can_copy_image(dst, src, this)); 1308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 130917b892551465e5a44560a06e4b34dc3592b49622egdaniel VkImageLayout origDstLayout = dstImage->currentLayout(); 131017b892551465e5a44560a06e4b34dc3592b49622egdaniel VkImageLayout origSrcLayout = srcImage->currentLayout(); 1311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 1313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 1314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if 1316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // the cache is flushed since it is only being written to. 1317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);; 1318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 13199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 132017b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage->setImageLayout(this, 132117b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 132217b892551465e5a44560a06e4b34dc3592b49622egdaniel srcAccessMask, 132317b892551465e5a44560a06e4b34dc3592b49622egdaniel dstAccessMask, 132417b892551465e5a44560a06e4b34dc3592b49622egdaniel srcStageMask, 132517b892551465e5a44560a06e4b34dc3592b49622egdaniel dstStageMask, 132617b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 13279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 1328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout); 1329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 1330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout); 1332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 1333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 133417b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage->setImageLayout(this, 133517b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 133617b892551465e5a44560a06e4b34dc3592b49622egdaniel srcAccessMask, 133717b892551465e5a44560a06e4b34dc3592b49622egdaniel dstAccessMask, 133817b892551465e5a44560a06e4b34dc3592b49622egdaniel srcStageMask, 133917b892551465e5a44560a06e4b34dc3592b49622egdaniel dstStageMask, 134017b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 1341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Flip rect if necessary 1343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkIRect srcVkRect = srcRect; 1344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int32_t dstY = dstPoint.fY; 1345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kBottomLeft_GrSurfaceOrigin == src->origin()) { 1347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin()); 1348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcVkRect.fTop = src->height() - srcRect.fBottom; 1349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcVkRect.fBottom = src->height() - srcRect.fTop; 1350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstY = dst->height() - dstPoint.fY - srcVkRect.height(); 1351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageCopy copyRegion; 1354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(©Region, 0, sizeof(VkImageCopy)); 1355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 1356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 }; 1357164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 1358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel copyRegion.dstOffset = { dstPoint.fX, dstY, 0 }; 1359c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel // The depth value of the extent is ignored according the vulkan spec for 2D images. However, on 1360c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel // at least the nexus 5X it seems to be checking it. Thus as a working around we must have the 1361c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel // depth value be 1. 1362c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 }; 1363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->copyImage(this, 136517b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage, 1366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 136717b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage, 1368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1, 1370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel ©Region); 1371900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 1372900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, 1373900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth srcRect.width(), srcRect.height()); 1374900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth this->didWriteToSurface(dst, &dstRect); 1375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 137717b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst, 137817b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrSurface* src, 137917b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkImage* dstImage, 138017b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkImage* srcImage, 138117b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkGpu* gpu) { 138217b892551465e5a44560a06e4b34dc3592b49622egdaniel // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src 138317b892551465e5a44560a06e4b34dc3592b49622egdaniel // as image usage flags. 138417b892551465e5a44560a06e4b34dc3592b49622egdaniel const GrVkCaps& caps = gpu->vkCaps(); 138517b892551465e5a44560a06e4b34dc3592b49622egdaniel if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) || 138617b892551465e5a44560a06e4b34dc3592b49622egdaniel !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) { 138717b892551465e5a44560a06e4b34dc3592b49622egdaniel return false; 138817b892551465e5a44560a06e4b34dc3592b49622egdaniel } 138917b892551465e5a44560a06e4b34dc3592b49622egdaniel 139017b892551465e5a44560a06e4b34dc3592b49622egdaniel // We cannot blit images that are multisampled. Will need to figure out if we can blit the 139117b892551465e5a44560a06e4b34dc3592b49622egdaniel // resolved msaa though. 139217b892551465e5a44560a06e4b34dc3592b49622egdaniel if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) || 139317b892551465e5a44560a06e4b34dc3592b49622egdaniel (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) { 139417b892551465e5a44560a06e4b34dc3592b49622egdaniel return false; 139517b892551465e5a44560a06e4b34dc3592b49622egdaniel } 139617b892551465e5a44560a06e4b34dc3592b49622egdaniel 139717b892551465e5a44560a06e4b34dc3592b49622egdaniel return true; 139817b892551465e5a44560a06e4b34dc3592b49622egdaniel} 139917b892551465e5a44560a06e4b34dc3592b49622egdaniel 140017b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst, 140117b892551465e5a44560a06e4b34dc3592b49622egdaniel GrSurface* src, 140217b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* dstImage, 140317b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* srcImage, 140417b892551465e5a44560a06e4b34dc3592b49622egdaniel const SkIRect& srcRect, 140517b892551465e5a44560a06e4b34dc3592b49622egdaniel const SkIPoint& dstPoint) { 140617b892551465e5a44560a06e4b34dc3592b49622egdaniel SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this)); 140717b892551465e5a44560a06e4b34dc3592b49622egdaniel 140817b892551465e5a44560a06e4b34dc3592b49622egdaniel VkImageLayout origDstLayout = dstImage->currentLayout(); 140917b892551465e5a44560a06e4b34dc3592b49622egdaniel VkImageLayout origSrcLayout = srcImage->currentLayout(); 141017b892551465e5a44560a06e4b34dc3592b49622egdaniel 141117b892551465e5a44560a06e4b34dc3592b49622egdaniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 141217b892551465e5a44560a06e4b34dc3592b49622egdaniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 141317b892551465e5a44560a06e4b34dc3592b49622egdaniel 141417b892551465e5a44560a06e4b34dc3592b49622egdaniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);; 141517b892551465e5a44560a06e4b34dc3592b49622egdaniel VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 141617b892551465e5a44560a06e4b34dc3592b49622egdaniel 141717b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage->setImageLayout(this, 141817b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 141917b892551465e5a44560a06e4b34dc3592b49622egdaniel srcAccessMask, 142017b892551465e5a44560a06e4b34dc3592b49622egdaniel dstAccessMask, 142117b892551465e5a44560a06e4b34dc3592b49622egdaniel srcStageMask, 142217b892551465e5a44560a06e4b34dc3592b49622egdaniel dstStageMask, 142317b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 142417b892551465e5a44560a06e4b34dc3592b49622egdaniel 142517b892551465e5a44560a06e4b34dc3592b49622egdaniel srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout); 142617b892551465e5a44560a06e4b34dc3592b49622egdaniel dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 142717b892551465e5a44560a06e4b34dc3592b49622egdaniel 142817b892551465e5a44560a06e4b34dc3592b49622egdaniel srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout); 142917b892551465e5a44560a06e4b34dc3592b49622egdaniel dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 143017b892551465e5a44560a06e4b34dc3592b49622egdaniel 143117b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage->setImageLayout(this, 143217b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 143317b892551465e5a44560a06e4b34dc3592b49622egdaniel srcAccessMask, 143417b892551465e5a44560a06e4b34dc3592b49622egdaniel dstAccessMask, 143517b892551465e5a44560a06e4b34dc3592b49622egdaniel srcStageMask, 143617b892551465e5a44560a06e4b34dc3592b49622egdaniel dstStageMask, 143717b892551465e5a44560a06e4b34dc3592b49622egdaniel false); 143817b892551465e5a44560a06e4b34dc3592b49622egdaniel 143917b892551465e5a44560a06e4b34dc3592b49622egdaniel // Flip rect if necessary 144017b892551465e5a44560a06e4b34dc3592b49622egdaniel SkIRect srcVkRect; 14418af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fLeft = srcRect.fLeft; 14428af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fRight = srcRect.fRight; 144317b892551465e5a44560a06e4b34dc3592b49622egdaniel SkIRect dstRect; 144417b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fLeft = dstPoint.fX; 14458af936d3047208def585b7bc824f013b994f6312egdaniel dstRect.fRight = dstPoint.fX + srcRect.width(); 144617b892551465e5a44560a06e4b34dc3592b49622egdaniel 144717b892551465e5a44560a06e4b34dc3592b49622egdaniel if (kBottomLeft_GrSurfaceOrigin == src->origin()) { 144817b892551465e5a44560a06e4b34dc3592b49622egdaniel srcVkRect.fTop = src->height() - srcRect.fBottom; 144917b892551465e5a44560a06e4b34dc3592b49622egdaniel srcVkRect.fBottom = src->height() - srcRect.fTop; 145017b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 14518af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fTop = srcRect.fTop; 14528af936d3047208def585b7bc824f013b994f6312egdaniel srcVkRect.fBottom = srcRect.fBottom; 145317b892551465e5a44560a06e4b34dc3592b49622egdaniel } 145417b892551465e5a44560a06e4b34dc3592b49622egdaniel 145517b892551465e5a44560a06e4b34dc3592b49622egdaniel if (kBottomLeft_GrSurfaceOrigin == dst->origin()) { 145617b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height(); 145717b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 145817b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fTop = dstPoint.fY; 145917b892551465e5a44560a06e4b34dc3592b49622egdaniel } 146017b892551465e5a44560a06e4b34dc3592b49622egdaniel dstRect.fBottom = dstRect.fTop + srcVkRect.height(); 146117b892551465e5a44560a06e4b34dc3592b49622egdaniel 146217b892551465e5a44560a06e4b34dc3592b49622egdaniel // If we have different origins, we need to flip the top and bottom of the dst rect so that we 146317b892551465e5a44560a06e4b34dc3592b49622egdaniel // get the correct origintation of the copied data. 146417b892551465e5a44560a06e4b34dc3592b49622egdaniel if (src->origin() != dst->origin()) { 146517b892551465e5a44560a06e4b34dc3592b49622egdaniel SkTSwap(dstRect.fTop, dstRect.fBottom); 146617b892551465e5a44560a06e4b34dc3592b49622egdaniel } 146717b892551465e5a44560a06e4b34dc3592b49622egdaniel 146817b892551465e5a44560a06e4b34dc3592b49622egdaniel VkImageBlit blitRegion; 146917b892551465e5a44560a06e4b34dc3592b49622egdaniel memset(&blitRegion, 0, sizeof(VkImageBlit)); 147017b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 147117b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 }; 147217b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 0 }; 147317b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 147417b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 }; 147517b892551465e5a44560a06e4b34dc3592b49622egdaniel blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 0 }; 147617b892551465e5a44560a06e4b34dc3592b49622egdaniel 147717b892551465e5a44560a06e4b34dc3592b49622egdaniel fCurrentCmdBuffer->blitImage(this, 147862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth srcImage->resource(), 147917b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 148062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth dstImage->resource(), 148117b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 148217b892551465e5a44560a06e4b34dc3592b49622egdaniel 1, 148317b892551465e5a44560a06e4b34dc3592b49622egdaniel &blitRegion, 148417b892551465e5a44560a06e4b34dc3592b49622egdaniel VK_FILTER_NEAREST); // We never scale so any filter works here 1485900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth 1486900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth this->didWriteToSurface(dst, &dstRect); 148717b892551465e5a44560a06e4b34dc3592b49622egdaniel} 148817b892551465e5a44560a06e4b34dc3592b49622egdaniel 1489164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst, 1490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrSurface* src, 1491164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const GrVkGpu* gpu) { 1492164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1493164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1494164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst, 1496164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurface* src, 1497164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIRect& srcRect, 1498164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIPoint& dstPoint) { 1499164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(false); 1500164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1501164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1502164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst, 1503164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrSurface* src, 1504164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIRect& srcRect, 1505164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const SkIPoint& dstPoint) { 150617b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* dstImage; 150717b892551465e5a44560a06e4b34dc3592b49622egdaniel GrVkImage* srcImage; 150817b892551465e5a44560a06e4b34dc3592b49622egdaniel if (dst->asTexture()) { 150917b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage = static_cast<GrVkTexture*>(dst->asTexture()); 151017b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 151117b892551465e5a44560a06e4b34dc3592b49622egdaniel SkASSERT(dst->asRenderTarget()); 151217b892551465e5a44560a06e4b34dc3592b49622egdaniel dstImage = static_cast<GrVkRenderTarget*>(dst->asRenderTarget()); 151317b892551465e5a44560a06e4b34dc3592b49622egdaniel } 151417b892551465e5a44560a06e4b34dc3592b49622egdaniel if (src->asTexture()) { 151517b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage = static_cast<GrVkTexture*>(src->asTexture()); 151617b892551465e5a44560a06e4b34dc3592b49622egdaniel } else { 151717b892551465e5a44560a06e4b34dc3592b49622egdaniel SkASSERT(src->asRenderTarget()); 151817b892551465e5a44560a06e4b34dc3592b49622egdaniel srcImage = static_cast<GrVkRenderTarget*>(src->asRenderTarget()); 151917b892551465e5a44560a06e4b34dc3592b49622egdaniel } 152017b892551465e5a44560a06e4b34dc3592b49622egdaniel 1521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (can_copy_image(dst, src, this)) { 152217b892551465e5a44560a06e4b34dc3592b49622egdaniel this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint); 152317b892551465e5a44560a06e4b34dc3592b49622egdaniel return true; 152417b892551465e5a44560a06e4b34dc3592b49622egdaniel } 152517b892551465e5a44560a06e4b34dc3592b49622egdaniel 152617b892551465e5a44560a06e4b34dc3592b49622egdaniel if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) { 152717b892551465e5a44560a06e4b34dc3592b49622egdaniel this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint); 1528164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1530164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (can_copy_as_draw(dst, src, this)) { 1532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); 1533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1534164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1536164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1537164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1538164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 153937798fbd82a7d064c5cc1516f120546a3408044begdanielbool GrVkGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const { 154037798fbd82a7d064c5cc1516f120546a3408044begdaniel // Currently we don't support msaa 154137798fbd82a7d064c5cc1516f120546a3408044begdaniel if (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1) { 154237798fbd82a7d064c5cc1516f120546a3408044begdaniel return false; 154337798fbd82a7d064c5cc1516f120546a3408044begdaniel } 154437798fbd82a7d064c5cc1516f120546a3408044begdaniel 154537798fbd82a7d064c5cc1516f120546a3408044begdaniel // This will support copying the dst as CopyImage since all of our surfaces require transferSrc 154637798fbd82a7d064c5cc1516f120546a3408044begdaniel // and transferDst usage flags in Vulkan. 154737798fbd82a7d064c5cc1516f120546a3408044begdaniel desc->fOrigin = src->origin(); 154837798fbd82a7d064c5cc1516f120546a3408044begdaniel desc->fConfig = src->config(); 154937798fbd82a7d064c5cc1516f120546a3408044begdaniel desc->fFlags = kNone_GrSurfaceFlags; 155037798fbd82a7d064c5cc1516f120546a3408044begdaniel return true; 155137798fbd82a7d064c5cc1516f120546a3408044begdaniel} 155237798fbd82a7d064c5cc1516f120546a3408044begdaniel 155328f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&, 155428f45b949acc746849100fbe112ee5280f0594c9cdalton int* effectiveSampleCnt, SkAutoTDeleteArray<SkPoint>*) { 155528f45b949acc746849100fbe112ee5280f0594c9cdalton // TODO: stub. 155628f45b949acc746849100fbe112ee5280f0594c9cdalton SkASSERT(!this->caps()->sampleLocationsSupport()); 155728f45b949acc746849100fbe112ee5280f0594c9cdalton *effectiveSampleCnt = rt->desc().fSampleCnt; 155828f45b949acc746849100fbe112ee5280f0594c9cdalton} 155928f45b949acc746849100fbe112ee5280f0594c9cdalton 1560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes, 1561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig readConfig, DrawPreference* drawPreference, 1562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel ReadPixelTempDrawInfo* tempDrawInfo) { 1563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail 1564164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (kNoDraw_DrawPreference != *drawPreference) { 1565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (srcSurface->config() != readConfig) { 1569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: This should fall back to drawing or copying to change config of srcSurface to match 1570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // that of readConfig. 1571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1575164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1577164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface, 1578164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int left, int top, int width, int height, 1579164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrPixelConfig config, 1580164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* buffer, 1581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t rowBytes) { 1582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkFormat pixelFormat; 1583164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { 1584164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1585164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1586164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture()); 1588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (!tgt) { 1589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 1590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Change layout of our target so it can be used as copy 1593164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageLayout layout = tgt->currentLayout(); 1594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); 1595164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 1596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); 1597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 1598164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tgt->setImageLayout(this, 1599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1600164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcAccessMask, 1601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstAccessMask, 1602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 16069d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary GrVkTransferBuffer* transferBuffer = 1607e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, 1608e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton kXferGpuToCpu_GrBufferType, 1609397536cabe12a9936659870dd220c869789424bacdalton kStream_GrAccessPattern)); 1610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); 1612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkOffset3D offset = { 1613164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel left, 1614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flipY ? surface->height() - top - height : top, 1615164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 0 1616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel }; 1617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Copy the image to a buffer so we can map it to cpu memory 1619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkBufferImageCopy region; 1620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memset(®ion, 0, sizeof(VkBufferImageCopy)); 1621164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.bufferOffset = 0; 1622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.bufferRowLength = 0; // Forces RowLength to be imageExtent.width 1623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images. 1624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 1625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.imageOffset = offset; 1626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; 1627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->copyImageToBuffer(this, 1629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel tgt, 1630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel transferBuffer, 1632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1, 1633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel ®ion); 1634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // make sure the copy to buffer has finished 1636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel transferBuffer->addMemoryBarrier(this, 1637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_ACCESS_TRANSFER_WRITE_BIT, 1638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_ACCESS_HOST_READ_BIT, 1639164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_PIPELINE_STAGE_TRANSFER_BIT, 1640164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_PIPELINE_STAGE_HOST_BIT, 1641164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1642164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We need to submit the current command buffer to the Queue and make sure it finishes before 1644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // we can copy the data out of the buffer. 1645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel this->submitCommandBuffer(kForce_SyncQueue); 1646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1647164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* mappedMemory = transferBuffer->map(); 1648164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memcpy(buffer, mappedMemory, rowBytes*height); 1650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel transferBuffer->unmap(); 1652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel transferBuffer->unref(); 1653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (flipY) { 1655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkAutoSMalloc<32 * sizeof(GrColor)> scratch; 1656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel size_t tightRowBytes = GrBytesPerPixel(config) * width; 1657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel scratch.reset(tightRowBytes); 1658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel void* tmpRow = scratch.get(); 1659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // flip y in-place by rows 1660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel const int halfY = height >> 1; 1661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel char* top = reinterpret_cast<char*>(buffer); 1662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel char* bottom = top + (height - 1) * rowBytes; 1663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel for (int y = 0; y < halfY; y++) { 1664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memcpy(tmpRow, top, tightRowBytes); 1665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memcpy(top, bottom, tightRowBytes); 1666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel memcpy(bottom, tmpRow, tightRowBytes); 1667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel top += rowBytes; 1668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel bottom -= rowBytes; 1669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 1673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1674af132770a9462f6bb9cff47254e44675d9241fe8egdanielsk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline, 1675af132770a9462f6bb9cff47254e44675d9241fe8egdaniel const GrPrimitiveProcessor& primProc, 1676af132770a9462f6bb9cff47254e44675d9241fe8egdaniel GrPrimitiveType primitiveType, 1677af132770a9462f6bb9cff47254e44675d9241fe8egdaniel const GrVkRenderPass& renderPass) { 1678af132770a9462f6bb9cff47254e44675d9241fe8egdaniel sk_sp<GrVkPipelineState> pipelineState = 1679af132770a9462f6bb9cff47254e44675d9241fe8egdaniel fResourceProvider.findOrCreateCompatiblePipelineState(pipeline, 1680af132770a9462f6bb9cff47254e44675d9241fe8egdaniel primProc, 1681af132770a9462f6bb9cff47254e44675d9241fe8egdaniel primitiveType, 1682af132770a9462f6bb9cff47254e44675d9241fe8egdaniel renderPass); 168322281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel if (!pipelineState) { 1684af132770a9462f6bb9cff47254e44675d9241fe8egdaniel return pipelineState; 1685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1687af132770a9462f6bb9cff47254e44675d9241fe8egdaniel pipelineState->setData(this, primProc, pipeline); 1688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1689af132770a9462f6bb9cff47254e44675d9241fe8egdaniel pipelineState->bind(this, fCurrentCmdBuffer); 1690470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel 1691470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline); 1692470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel 1693af132770a9462f6bb9cff47254e44675d9241fe8egdaniel return pipelineState; 16940e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel} 1695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 16960e1853c89615d14d0d03c87c7e0c604e5285cc54egdanielvoid GrVkGpu::onDraw(const GrPipeline& pipeline, 16970e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrPrimitiveProcessor& primProc, 16980e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrMesh* meshes, 16990e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel int meshCount) { 17000e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel if (!meshCount) { 17010e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel return; 17020e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } 17030e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel GrRenderTarget* rt = pipeline.getRenderTarget(); 17040e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); 17050e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); 17060e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel SkASSERT(renderPass); 1707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 17080e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel GrPrimitiveType primitiveType = meshes[0].primitiveType(); 1709af132770a9462f6bb9cff47254e44675d9241fe8egdaniel sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline, 1710af132770a9462f6bb9cff47254e44675d9241fe8egdaniel primProc, 1711af132770a9462f6bb9cff47254e44675d9241fe8egdaniel primitiveType, 1712af132770a9462f6bb9cff47254e44675d9241fe8egdaniel *renderPass); 1713af132770a9462f6bb9cff47254e44675d9241fe8egdaniel if (!pipelineState) { 17140e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel return; 17150e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } 1716164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1717164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Change layout of our render target so it can be used as the color attachment 1718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImageLayout layout = vkRT->currentLayout(); 1719164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); 1720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 1721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); 1722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel vkRT->setImageLayout(this, 1724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcAccessMask, 1726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstAccessMask, 1727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel srcStageMask, 1728164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel dstStageMask, 1729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel false); 1730164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 17313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel // If we are using a stencil attachment we also need to update its layout 173258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) { 17333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; 17343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkImageLayout origDstLayout = vkStencil->currentLayout(); 17353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); 17363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 17370e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; 17383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkPipelineStageFlags srcStageMask = 17393d5d9ac426ea926f37eaa47e13acf7492068667begdaniel GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); 17403d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 17413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel vkStencil->setImageLayout(this, 17423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 17433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel srcAccessMask, 17443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel dstAccessMask, 17453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel srcStageMask, 17463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel dstStageMask, 17473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel false); 17483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel } 17493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel 175058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); 17510e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 17520e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel for (int i = 0; i < meshCount; ++i) { 17530e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrMesh& mesh = meshes[i]; 17540e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel GrMesh::Iterator iter; 17550e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh); 17560e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel do { 17570e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel if (nonIdxMesh->primitiveType() != primitiveType) { 17580e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel // Technically we don't have to call this here (since there is a safety check in 175922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel // pipelineState:setData but this will allow for quicker freeing of resources if the 176022281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel // pipelineState sits in a cache for a while. 176122281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel pipelineState->freeTempResources(this); 176222281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel SkDEBUGCODE(pipelineState = nullptr); 17630e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel primitiveType = nonIdxMesh->primitiveType(); 1764af132770a9462f6bb9cff47254e44675d9241fe8egdaniel pipelineState = this->prepareDrawState(pipeline, 1765af132770a9462f6bb9cff47254e44675d9241fe8egdaniel primProc, 1766af132770a9462f6bb9cff47254e44675d9241fe8egdaniel primitiveType, 1767af132770a9462f6bb9cff47254e44675d9241fe8egdaniel *renderPass); 1768af132770a9462f6bb9cff47254e44675d9241fe8egdaniel if (!pipelineState) { 17690e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel return; 17700e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } 17710e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } 177222281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel SkASSERT(pipelineState); 17730e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel this->bindGeometry(primProc, *nonIdxMesh); 17740e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 17750e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel if (nonIdxMesh->isIndexed()) { 17760e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel fCurrentCmdBuffer->drawIndexed(this, 17770e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel nonIdxMesh->indexCount(), 17780e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 1, 17790e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel nonIdxMesh->startIndex(), 17800e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel nonIdxMesh->startVertex(), 17810e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 0); 17820e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } else { 17830e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel fCurrentCmdBuffer->draw(this, 17840e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel nonIdxMesh->vertexCount(), 17850e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 1, 17860e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel nonIdxMesh->startVertex(), 17870e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 0); 17880e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } 17890e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel 17900e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel fStats.incNumDraws(); 17910e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel } while ((nonIdxMesh = iter.next())); 1792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1793164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1794164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel fCurrentCmdBuffer->endRenderPass(this); 1795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 179622281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel // Technically we don't have to call this here (since there is a safety check in 179722281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel // pipelineState:setData but this will allow for quicker freeing of resources if the 179822281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel // pipelineState sits in a cache for a while. 179922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel pipelineState->freeTempResources(this); 1800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if SWAP_PER_DRAW 1802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel glFlush(); 1803164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if defined(SK_BUILD_FOR_MAC) 1804164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel aglSwapBuffers(aglGetCurrentContext()); 1805164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int set_a_break_pt_here = 9; 1806164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel aglSwapBuffers(aglGetCurrentContext()); 1807164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#elif defined(SK_BUILD_FOR_WIN32) 1808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SwapBuf(); 1809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel int set_a_break_pt_here = 9; 1810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SwapBuf(); 1811164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif 1812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif 1813164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 1814