xref: /aosp_15_r20/external/skia/tests/BackendSurfaceMutableStateTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
9 #include "tests/Test.h"
10 
11 #ifdef SK_VULKAN
12 #include "include/core/SkAlphaType.h"
13 #include "include/core/SkColorSpace.h"
14 #include "include/core/SkColorType.h"
15 #include "include/core/SkImage.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/gpu/GpuTypes.h"
18 #include "include/gpu/ganesh/GrBackendSurface.h"
19 #include "include/gpu/ganesh/GrDirectContext.h"
20 #include "include/gpu/ganesh/GrTypes.h"
21 #include "include/gpu/MutableTextureState.h"
22 #include "include/gpu/ganesh/SkImageGanesh.h"
23 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
24 #include "include/gpu/ganesh/vk/GrVkTypes.h"
25 #include "include/gpu/vk/VulkanMutableTextureState.h"
26 #include "src/gpu/ganesh/GrDirectContextPriv.h"
27 #include "src/gpu/ganesh/GrSurfaceProxy.h"
28 #include "src/gpu/ganesh/GrTextureProxy.h"
29 #include "src/gpu/ganesh/vk/GrVkCaps.h"
30 #include "src/gpu/ganesh/vk/GrVkGpu.h"
31 #include "src/gpu/ganesh/vk/GrVkImage.h"
32 #include "src/gpu/ganesh/vk/GrVkTexture.h"
33 #include "tests/CtsEnforcement.h"
34 #include "tools/gpu/ProxyUtils.h"
35 
36 #include <vulkan/vulkan_core.h>
37 #include <cstdint>
38 
39 class GrTexture;
40 struct GrContextOptions;
41 
42 using skgpu::MutableTextureStates::GetVkImageLayout;
43 using skgpu::MutableTextureStates::GetVkQueueFamilyIndex;
44 
DEF_GANESH_TEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)45 DEF_GANESH_TEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest,
46                                    reporter,
47                                    ctxInfo,
48                                    CtsEnforcement::kApiLevel_T) {
49     using namespace skgpu;
50 
51     auto dContext = ctxInfo.directContext();
52 
53     Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());
54 
55     GrBackendFormat format = GrBackendFormats::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
56     GrBackendTexture backendTex = dContext->createBackendTexture(
57             32, 32, format, Mipmapped::kNo, GrRenderable::kNo, isProtected);
58 
59     REPORTER_ASSERT(reporter, backendTex.isValid());
60 
61     GrVkImageInfo info;
62     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
63     VkImageLayout initLayout = info.fImageLayout;
64     uint32_t initQueue = info.fCurrentQueueFamily;
65     MutableTextureState initState = skgpu::MutableTextureStates::MakeVulkan(initLayout, initQueue);
66 
67     // Verify that setting that state via a copy of a backendTexture is reflected in all the
68     // backendTextures.
69     GrBackendTexture backendTexCopy = backendTex;
70     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTexCopy, &info));
71     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
72     REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
73 
74     MutableTextureState newState = skgpu::MutableTextureStates::MakeVulkan(
75             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_QUEUE_FAMILY_IGNORED);
76     backendTexCopy.setMutableState(newState);
77 
78     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
79     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
80     REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_IGNORED == info.fCurrentQueueFamily);
81 
82     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTexCopy, &info));
83     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
84     REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_IGNORED == info.fCurrentQueueFamily);
85 
86     // Setting back to the init state since we didn't actually change it
87     backendTex.setMutableState(initState);
88 
89     sk_sp<SkImage> wrappedImage = SkImages::BorrowTextureFrom(dContext,
90                                                               backendTex,
91                                                               kTopLeft_GrSurfaceOrigin,
92                                                               kRGBA_8888_SkColorType,
93                                                               kPremul_SkAlphaType,
94                                                               nullptr);
95 
96     GrSurfaceProxy* proxy = sk_gpu_test::GetTextureImageProxy(wrappedImage.get(), dContext);
97 
98     REPORTER_ASSERT(reporter, proxy);
99     REPORTER_ASSERT(reporter, proxy->isInstantiated());
100     GrTexture* texture = proxy->peekTexture();
101     REPORTER_ASSERT(reporter, texture);
102 
103     // Verify that modifying the layout via the GrVkTexture is reflected in the GrBackendTexture
104     GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage();
105     REPORTER_ASSERT(reporter, initLayout == vkTexture->currentLayout());
106     REPORTER_ASSERT(reporter, initQueue == vkTexture->currentQueueFamilyIndex());
107     vkTexture->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
108 
109     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
110     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == info.fImageLayout);
111     REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
112 
113     GrBackendTexture backendTexImage;
114     bool ok = SkImages::GetBackendTextureFromImage(wrappedImage, &backendTexImage, false);
115     REPORTER_ASSERT(reporter, ok);
116     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTexImage, &info));
117     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == info.fImageLayout);
118     REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
119 
120     // Verify that modifying the layout via the GrBackendTexutre is reflected in the GrVkTexture
121     backendTexImage.setMutableState(newState);
122     REPORTER_ASSERT(reporter,
123                     VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == vkTexture->currentLayout());
124     REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_IGNORED == info.fCurrentQueueFamily);
125 
126     vkTexture->setQueueFamilyIndex(initQueue);
127     vkTexture->updateImageLayout(initLayout);
128 
129     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
130     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
131     REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
132 
133     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTexCopy, &info));
134     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
135     REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
136 
137     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTexImage, &info));
138     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
139     REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
140 
141     // Test using the setBackendTextureStateAPI. Unlike the previous test this will actually add
142     // real transitions to the image so we need to be careful about doing actual valid transitions.
143     GrVkGpu* gpu = static_cast<GrVkGpu*>(dContext->priv().getGpu());
144 
145     MutableTextureState previousState;
146 
147     dContext->setBackendTextureState(backendTex, newState, &previousState);
148 
149     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
150     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
151     REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
152 
153     REPORTER_ASSERT(reporter, previousState.isValid());
154     REPORTER_ASSERT(reporter, previousState.backend() == BackendApi::kVulkan);
155     REPORTER_ASSERT(reporter, GetVkImageLayout(previousState) == initLayout);
156     REPORTER_ASSERT(reporter, GetVkQueueFamilyIndex(previousState) == initQueue);
157 
158     // Make sure passing in VK_IMAGE_LAYOUT_UNDEFINED does not change the layout
159     MutableTextureState noopState = skgpu::MutableTextureStates::MakeVulkan(
160             VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_IGNORED);
161     dContext->setBackendTextureState(backendTex, noopState, &previousState);
162     REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
163     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
164     REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
165 
166     REPORTER_ASSERT(reporter, previousState.isValid());
167     REPORTER_ASSERT(reporter, previousState.backend() == BackendApi::kVulkan);
168     REPORTER_ASSERT(reporter,
169                     GetVkImageLayout(previousState) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
170     REPORTER_ASSERT(reporter, GetVkQueueFamilyIndex(previousState) == gpu->queueIndex());
171 
172     // To test queue transitions, we don't have any other valid queue available so instead we try
173     // to transition to external queue.
174     if (gpu->vkCaps().supportsExternalMemory()) {
175         MutableTextureState externalState = skgpu::MutableTextureStates::MakeVulkan(
176                 VK_IMAGE_LAYOUT_GENERAL, VK_QUEUE_FAMILY_EXTERNAL);
177 
178         dContext->setBackendTextureState(backendTex, externalState, &previousState);
179 
180         REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
181         REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout);
182         REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_EXTERNAL == info.fCurrentQueueFamily);
183 
184         REPORTER_ASSERT(reporter, previousState.isValid());
185         REPORTER_ASSERT(reporter, previousState.backend() == BackendApi::kVulkan);
186         REPORTER_ASSERT(reporter,
187                 GetVkImageLayout(previousState) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
188         REPORTER_ASSERT(reporter, GetVkQueueFamilyIndex(previousState) == gpu->queueIndex());
189 
190         dContext->submit();
191 
192         // Go back to the initial queue. Also we should stay in VK_IMAGE_LAYOUT_GENERAL since we
193         // are passing in VK_IMAGE_LAYOUT_UNDEFINED
194         MutableTextureState externalState2 =
195                 skgpu::MutableTextureStates::MakeVulkan(VK_IMAGE_LAYOUT_UNDEFINED, initQueue);
196         dContext->setBackendTextureState(backendTex, externalState2, &previousState);
197 
198         REPORTER_ASSERT(reporter, GrBackendTextures::GetVkImageInfo(backendTex, &info));
199         REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout);
200         REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
201 
202         REPORTER_ASSERT(reporter, previousState.isValid());
203         REPORTER_ASSERT(reporter, previousState.backend() == BackendApi::kVulkan);
204         REPORTER_ASSERT(reporter, GetVkImageLayout(previousState) == VK_IMAGE_LAYOUT_GENERAL);
205         REPORTER_ASSERT(reporter, GetVkQueueFamilyIndex(previousState) == VK_QUEUE_FAMILY_EXTERNAL);
206     }
207 
208     // We must submit this work before we try to delete the backend texture.
209     dContext->submit(GrSyncCpu::kYes);
210 
211     dContext->deleteBackendTexture(backendTex);
212 }
213 
214 #endif
215