• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google Inc.
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 "tools/gpu/vk/VkTestHelper.h"
9 
10 #if defined(SK_VULKAN)
11 
12 #include "include/core/SkSurface.h"
13 #include "include/gpu/GrTypes.h"
14 #include "include/gpu/vk/VulkanBackendContext.h"
15 #include "include/gpu/vk/VulkanMemoryAllocator.h"
16 #include "tests/TestType.h"
17 #include "tools/gpu/ProtectedUtils.h"
18 #include "tools/gpu/vk/VkTestUtils.h"
19 
20 #if defined(SK_GANESH)
21 #include "include/gpu/GrDirectContext.h"
22 #include "include/gpu/ganesh/vk/GrVkDirectContext.h"
23 #endif
24 
25 #if defined(SK_GRAPHITE)
26 #include "include/gpu/graphite/Context.h"
27 #include "include/gpu/graphite/vk/VulkanGraphiteUtils.h"
28 #include "include/private/gpu/graphite/ContextOptionsPriv.h"
29 #endif
30 
31 #define ACQUIRE_INST_VK_PROC(name)                                                               \
32     fVk##name = reinterpret_cast<PFN_vk##name>(instProc(fBackendContext.fInstance, "vk" #name)); \
33     if (fVk##name == nullptr) {                                                                  \
34         SkDebugf("Function ptr for vk%s could not be acquired\n", #name);                        \
35         return false;                                                                            \
36     }
37 
38 #define ACQUIRE_DEVICE_VK_PROC(name)                                                          \
39     fVk##name = reinterpret_cast<PFN_vk##name>(fVkGetDeviceProcAddr(fDevice, "vk" #name));    \
40     if (fVk##name == nullptr) {                                                               \
41         SkDebugf("Function ptr for vk%s could not be acquired\n", #name);                     \
42         return false;                                                                         \
43     }
44 
45 #if defined(SK_GANESH)
46 
47 class GaneshVkTestHelper : public VkTestHelper {
48 public:
GaneshVkTestHelper(bool isProtected)49     GaneshVkTestHelper(bool isProtected) : VkTestHelper(isProtected) {}
50 
~GaneshVkTestHelper()51     ~GaneshVkTestHelper() override {
52         // Make sure any work, release procs, etc left on the context are finished with before we
53         // start tearing everything down.
54         if (fDirectContext) {
55             fDirectContext->flushAndSubmit(GrSyncCpu::kYes);
56         }
57 
58         fDirectContext.reset();
59     }
60 
isValid() const61     bool isValid() const override { return fDirectContext != nullptr; }
62 
createSurface(SkISize size,bool textureable,bool isProtected)63     sk_sp<SkSurface> createSurface(SkISize size, bool textureable, bool isProtected) override {
64         // Make Ganesh use DMSAA to better match Graphite's behavior
65         SkSurfaceProps props(SkSurfaceProps::kDynamicMSAA_Flag, kUnknown_SkPixelGeometry);
66 
67         return ProtectedUtils::CreateProtectedSkSurface(fDirectContext.get(), size,
68                                                         textureable, isProtected,
69                                                         &props);
70     }
71 
submitAndWaitForCompletion(bool * completionMarker)72     void submitAndWaitForCompletion(bool* completionMarker) override {
73         fDirectContext->submit();
74         while (!*completionMarker) {
75             fDirectContext->checkAsyncWorkCompletion();
76         }
77     }
78 
directContext()79     GrDirectContext* directContext() override { return fDirectContext.get(); }
80 
81 protected:
init()82     bool init() override {
83         if (!this->setupBackendContext()) {
84             return false;
85         }
86 
87         fDirectContext = GrDirectContexts::MakeVulkan(fBackendContext);
88         if (!fDirectContext) {
89             return false;
90         }
91 
92         SkASSERT(fDirectContext->supportsProtectedContent() == fIsProtected);
93         return true;
94     }
95 
96 private:
97     sk_sp<GrDirectContext> fDirectContext;
98 };
99 
100 #endif // SK_GANESH
101 
102 #if defined(SK_GRAPHITE)
103 
104 class GraphiteVkTestHelper : public VkTestHelper {
105 public:
GraphiteVkTestHelper(bool isProtected)106     GraphiteVkTestHelper(bool isProtected) : VkTestHelper(isProtected) {}
107 
~GraphiteVkTestHelper()108     ~GraphiteVkTestHelper() override {
109         // Make sure any work, release procs, etc left on the context are finished with before we
110         // start tearing everything down.
111 
112         std::unique_ptr<skgpu::graphite::Recording> recording;
113         if (fRecorder) {
114             recording = fRecorder->snap();
115         }
116 
117         if (fContext) {
118             fContext->insertRecording({ recording.get() });
119             fContext->submit(skgpu::graphite::SyncToCpu::kYes);
120         }
121 
122         recording.reset();
123         fRecorder.reset();
124         fContext.reset();
125     }
126 
isValid() const127     bool isValid() const override { return fContext != nullptr && fRecorder != nullptr; }
128 
createSurface(SkISize size,bool,bool isProtected)129     sk_sp<SkSurface> createSurface(SkISize size,
130                                    bool /* textureable */,
131                                    bool isProtected) override {
132         return ProtectedUtils::CreateProtectedSkSurface(fRecorder.get(), size,
133                                                         skgpu::Protected(isProtected));
134     }
135 
submitAndWaitForCompletion(bool * completionMarker)136     void submitAndWaitForCompletion(bool* completionMarker) override {
137         fContext->submit();
138         while (!*completionMarker) {
139             fContext->checkAsyncWorkCompletion();
140         }
141     }
142 
recorder()143     skgpu::graphite::Recorder* recorder() override { return fRecorder.get(); }
144 
145 protected:
init()146     bool init() override {
147         if (!this->setupBackendContext()) {
148             return false;
149         }
150 
151         skgpu::graphite::ContextOptions contextOptions;
152         skgpu::graphite::ContextOptionsPriv contextOptionsPriv;
153         // Needed to make ManagedGraphiteTexture::ReleaseProc (w/in CreateProtectedSkSurface) work
154         contextOptionsPriv.fStoreContextRefInRecorder = true;
155         contextOptions.fOptionsPriv = &contextOptionsPriv;
156 
157         fContext = skgpu::graphite::ContextFactory::MakeVulkan(fBackendContext, contextOptions);
158         if (!fContext) {
159             return false;
160         }
161 
162         SkASSERT(fContext->supportsProtectedContent() == fIsProtected);
163 
164         fRecorder = fContext->makeRecorder();
165         if (!fRecorder) {
166             return false;
167         }
168 
169         return true;
170     }
171 
172 private:
173     std::unique_ptr<skgpu::graphite::Context> fContext;
174     std::unique_ptr<skgpu::graphite::Recorder> fRecorder;
175 };
176 
177 #endif // SK_GRAPHITE
178 
Make(skiatest::TestType testType,bool isProtected)179 std::unique_ptr<VkTestHelper> VkTestHelper::Make(skiatest::TestType testType,
180                                                  bool isProtected) {
181     std::unique_ptr<VkTestHelper> helper;
182 
183     switch (testType) {
184 #if defined(SK_GANESH)
185         case skiatest::TestType::kGanesh:
186             helper = std::make_unique<GaneshVkTestHelper>(isProtected);
187             break;
188 #endif
189 #if defined(SK_GRAPHITE)
190         case skiatest::TestType::kGraphite:
191             helper = std::make_unique<GraphiteVkTestHelper>(isProtected);
192             break;
193 #endif
194         default:
195             return nullptr;
196     }
197     if (!helper->init()) {
198         return nullptr;
199     }
200 
201     return helper;
202 }
203 
setupBackendContext()204 bool VkTestHelper::setupBackendContext() {
205     PFN_vkGetInstanceProcAddr instProc;
206     if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
207         return false;
208     }
209 
210     fFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
211     fFeatures.pNext = nullptr;
212 
213     fBackendContext.fInstance = VK_NULL_HANDLE;
214     fBackendContext.fDevice = VK_NULL_HANDLE;
215 
216     if (!sk_gpu_test::CreateVkBackendContext(instProc, &fBackendContext, &fExtensions,
217                                              &fFeatures, &fDebugCallback, nullptr,
218                                              sk_gpu_test::CanPresentFn(), fIsProtected)) {
219         return false;
220     }
221     fDevice = fBackendContext.fDevice;
222 
223     if (fDebugCallback != VK_NULL_HANDLE) {
224         fDestroyDebugCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
225                 instProc(fBackendContext.fInstance, "vkDestroyDebugReportCallbackEXT"));
226     }
227     ACQUIRE_INST_VK_PROC(DestroyInstance)
228     ACQUIRE_INST_VK_PROC(DeviceWaitIdle)
229     ACQUIRE_INST_VK_PROC(DestroyDevice)
230 
231     ACQUIRE_INST_VK_PROC(GetPhysicalDeviceFormatProperties)
232     ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties)
233 
234     ACQUIRE_INST_VK_PROC(GetDeviceProcAddr)
235 
236     ACQUIRE_DEVICE_VK_PROC(CreateImage)
237     ACQUIRE_DEVICE_VK_PROC(DestroyImage)
238     ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements)
239     ACQUIRE_DEVICE_VK_PROC(AllocateMemory)
240     ACQUIRE_DEVICE_VK_PROC(FreeMemory)
241     ACQUIRE_DEVICE_VK_PROC(BindImageMemory)
242     ACQUIRE_DEVICE_VK_PROC(MapMemory)
243     ACQUIRE_DEVICE_VK_PROC(UnmapMemory)
244     ACQUIRE_DEVICE_VK_PROC(FlushMappedMemoryRanges)
245     ACQUIRE_DEVICE_VK_PROC(GetImageSubresourceLayout)
246     return true;
247 }
248 
~VkTestHelper()249 VkTestHelper::~VkTestHelper() {
250     fBackendContext.fMemoryAllocator.reset();
251     if (fDevice != VK_NULL_HANDLE) {
252         fVkDeviceWaitIdle(fDevice);
253         fVkDestroyDevice(fDevice, nullptr);
254         fDevice = VK_NULL_HANDLE;
255     }
256     if (fDebugCallback != VK_NULL_HANDLE) {
257         fDestroyDebugCallback(fBackendContext.fInstance, fDebugCallback, nullptr);
258     }
259 
260     if (fBackendContext.fInstance != VK_NULL_HANDLE) {
261         fVkDestroyInstance(fBackendContext.fInstance, nullptr);
262         fBackendContext.fInstance = VK_NULL_HANDLE;
263     }
264 
265     sk_gpu_test::FreeVulkanFeaturesStructs(&fFeatures);
266 }
267 
268 #endif // SK_VULKAN
269