1/* 2 * Copyright 2020 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "include/core/SkImage.h" 9#include "include/gpu/GrBackendSurface.h" 10#include "include/gpu/GrDirectContext.h" 11#include "include/gpu/vk/GrVkTypes.h" 12#include "src/gpu/GrDirectContextPriv.h" 13#include "src/gpu/GrTexture.h" 14#include "src/gpu/GrTextureProxy.h" 15#include "src/image/SkImage_Base.h" 16#include "tests/Test.h" 17#include "tools/gpu/ProxyUtils.h" 18 19#ifdef SK_VULKAN 20#include "src/gpu/vk/GrVkGpu.h" 21#include "src/gpu/vk/GrVkTexture.h" 22 23DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest, reporter, ctxInfo) { 24 auto dContext = ctxInfo.directContext(); 25 26 GrBackendFormat format = GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM); 27 GrBackendTexture backendTex = dContext->createBackendTexture( 28 32, 32, format, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo); 29 30 REPORTER_ASSERT(reporter, backendTex.isValid()); 31 32 GrVkImageInfo info; 33 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 34 VkImageLayout initLayout = info.fImageLayout; 35 uint32_t initQueue = info.fCurrentQueueFamily; 36 GrBackendSurfaceMutableState initState(initLayout, initQueue); 37 38 // Verify that setting that state via a copy of a backendTexture is reflected in all the 39 // backendTextures. 40 GrBackendTexture backendTexCopy = backendTex; 41 REPORTER_ASSERT(reporter, backendTexCopy.getVkImageInfo(&info)); 42 REPORTER_ASSERT(reporter, initLayout == info.fImageLayout); 43 REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily); 44 45 GrBackendSurfaceMutableState newState(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 46 VK_QUEUE_FAMILY_IGNORED); 47 backendTexCopy.setMutableState(newState); 48 49 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 50 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout); 51 REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_IGNORED == info.fCurrentQueueFamily); 52 53 REPORTER_ASSERT(reporter, backendTexCopy.getVkImageInfo(&info)); 54 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout); 55 REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_IGNORED == info.fCurrentQueueFamily); 56 57 // Setting back to the init state since we didn't actually change it 58 backendTex.setMutableState(initState); 59 60 sk_sp<SkImage> wrappedImage = SkImage::MakeFromTexture(dContext, backendTex, 61 kTopLeft_GrSurfaceOrigin, 62 kRGBA_8888_SkColorType, 63 kPremul_SkAlphaType, nullptr); 64 65 GrSurfaceProxy* proxy = sk_gpu_test::GetTextureImageProxy(wrappedImage.get(), dContext); 66 67 REPORTER_ASSERT(reporter, proxy); 68 REPORTER_ASSERT(reporter, proxy->isInstantiated()); 69 GrTexture* texture = proxy->peekTexture(); 70 REPORTER_ASSERT(reporter, texture); 71 72 // Verify that modifying the layout via the GrVkTexture is reflected in the GrBackendTexture 73 GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage(); 74 REPORTER_ASSERT(reporter, initLayout == vkTexture->currentLayout()); 75 REPORTER_ASSERT(reporter, initQueue == vkTexture->currentQueueFamilyIndex()); 76 vkTexture->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 77 78 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 79 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == info.fImageLayout); 80 REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily); 81 82 GrBackendTexture backendTexImage = wrappedImage->getBackendTexture(false); 83 REPORTER_ASSERT(reporter, backendTexImage.getVkImageInfo(&info)); 84 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == info.fImageLayout); 85 REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily); 86 87 // Verify that modifying the layout via the GrBackendTexutre is reflected in the GrVkTexture 88 backendTexImage.setMutableState(newState); 89 REPORTER_ASSERT(reporter, 90 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == vkTexture->currentLayout()); 91 REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_IGNORED == info.fCurrentQueueFamily); 92 93 vkTexture->setQueueFamilyIndex(initQueue); 94 vkTexture->updateImageLayout(initLayout); 95 96 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 97 REPORTER_ASSERT(reporter, initLayout == info.fImageLayout); 98 REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily); 99 100 REPORTER_ASSERT(reporter, backendTexCopy.getVkImageInfo(&info)); 101 REPORTER_ASSERT(reporter, initLayout == info.fImageLayout); 102 REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily); 103 104 REPORTER_ASSERT(reporter, backendTexImage.getVkImageInfo(&info)); 105 REPORTER_ASSERT(reporter, initLayout == info.fImageLayout); 106 REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily); 107 108 // Test using the setBackendTextureStateAPI. Unlike the previous test this will actually add 109 // real transitions to the image so we need to be careful about doing actual valid transitions. 110 GrVkGpu* gpu = static_cast<GrVkGpu*>(dContext->priv().getGpu()); 111 112 GrBackendSurfaceMutableState previousState; 113 114 dContext->setBackendTextureState(backendTex, newState, &previousState); 115 116 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 117 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout); 118 REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily); 119 120 REPORTER_ASSERT(reporter, previousState.isValid()); 121 REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan); 122 REPORTER_ASSERT(reporter, previousState.getVkImageLayout() == initLayout); 123 REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == initQueue); 124 125 // Make sure passing in VK_IMAGE_LAYOUT_UNDEFINED does not change the layout 126 GrBackendSurfaceMutableState noopState(VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_IGNORED); 127 dContext->setBackendTextureState(backendTex, noopState, &previousState); 128 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 129 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout); 130 REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily); 131 132 REPORTER_ASSERT(reporter, previousState.isValid()); 133 REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan); 134 REPORTER_ASSERT(reporter, 135 previousState.getVkImageLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 136 REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == gpu->queueIndex()); 137 138 // To test queue transitions, we don't have any other valid queue available so instead we try 139 // to transition to external queue. 140 if (gpu->vkCaps().supportsExternalMemory()) { 141 GrBackendSurfaceMutableState externalState(VK_IMAGE_LAYOUT_GENERAL, 142 VK_QUEUE_FAMILY_EXTERNAL); 143 144 dContext->setBackendTextureState(backendTex, externalState, &previousState); 145 146 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 147 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout); 148 REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_EXTERNAL == info.fCurrentQueueFamily); 149 150 REPORTER_ASSERT(reporter, previousState.isValid()); 151 REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan); 152 REPORTER_ASSERT(reporter, 153 previousState.getVkImageLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 154 REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == gpu->queueIndex()); 155 156 dContext->submit(); 157 158 // Go back to the initial queue. Also we should stay in VK_IMAGE_LAYOUT_GENERAL since we 159 // are passing in VK_IMAGE_LAYOUT_UNDEFINED 160 GrBackendSurfaceMutableState externalState2(VK_IMAGE_LAYOUT_UNDEFINED, initQueue); 161 dContext->setBackendTextureState(backendTex, externalState2, &previousState); 162 163 REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info)); 164 REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout); 165 REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily); 166 167 REPORTER_ASSERT(reporter, previousState.isValid()); 168 REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan); 169 REPORTER_ASSERT(reporter, previousState.getVkImageLayout() == VK_IMAGE_LAYOUT_GENERAL); 170 REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == VK_QUEUE_FAMILY_EXTERNAL); 171 } 172 173 // We must submit this work before we try to delete the backend texture. 174 dContext->submit(true); 175 176 dContext->deleteBackendTexture(backendTex); 177} 178 179#endif 180