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