1 /*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "GaneshVkRenderEngine.h"
18
19 #undef LOG_TAG
20 #define LOG_TAG "RenderEngine"
21
22 #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
23
24 #include <log/log_main.h>
25 #include <sync/sync.h>
26 #include <utils/Trace.h>
27
28 namespace android::renderengine::skia {
29
create(const RenderEngineCreationArgs & args)30 std::unique_ptr<GaneshVkRenderEngine> GaneshVkRenderEngine::create(
31 const RenderEngineCreationArgs& args) {
32 std::unique_ptr<GaneshVkRenderEngine> engine(new GaneshVkRenderEngine(args));
33 engine->ensureContextsCreated();
34
35 if (getVulkanInterface(false).isInitialized()) {
36 ALOGD("GaneshVkRenderEngine::%s: successfully initialized GaneshVkRenderEngine", __func__);
37 return engine;
38 } else {
39 ALOGE("GaneshVkRenderEngine::%s: could not create GaneshVkRenderEngine. "
40 "Likely insufficient Vulkan support",
41 __func__);
42 return {};
43 }
44 }
45
46 // Ganesh-specific function signature for fFinishedProc callback.
unref_semaphore(void * semaphore)47 static void unref_semaphore(void* semaphore) {
48 SkiaVkRenderEngine::DestroySemaphoreInfo* info =
49 reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
50 info->unref();
51 }
52
createContext(VulkanInterface & vulkanInterface)53 std::unique_ptr<SkiaGpuContext> GaneshVkRenderEngine::createContext(
54 VulkanInterface& vulkanInterface) {
55 return SkiaGpuContext::MakeVulkan_Ganesh(vulkanInterface.getGaneshBackendContext(),
56 mSkSLCacheMonitor);
57 }
58
waitFence(SkiaGpuContext * context,base::borrowed_fd fenceFd)59 void GaneshVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
60 if (fenceFd.get() < 0) return;
61
62 const int dupedFd = dup(fenceFd.get());
63 if (dupedFd < 0) {
64 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
65 sync_wait(fenceFd.get(), -1);
66 return;
67 }
68
69 base::unique_fd fenceDup(dupedFd);
70 VkSemaphore waitSemaphore =
71 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
72 GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
73 constexpr bool kDeleteAfterWait = true;
74 context->grDirectContext()->wait(1, &beSemaphore, kDeleteAfterWait);
75 }
76
flushAndSubmit(SkiaGpuContext * context,sk_sp<SkSurface> dstSurface)77 base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context,
78 sk_sp<SkSurface> dstSurface) {
79 sk_sp<GrDirectContext> grContext = context->grDirectContext();
80 {
81 ATRACE_NAME("flush surface");
82 // TODO: Investigate feasibility of combining this "surface flush" into the "context flush"
83 // below.
84 context->grDirectContext()->flush(dstSurface.get());
85 }
86
87 VulkanInterface& vi = getVulkanInterface(isProtected());
88 VkSemaphore semaphore = vi.createExportableSemaphore();
89 GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
90
91 GrFlushInfo flushInfo;
92 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
93 if (semaphore != VK_NULL_HANDLE) {
94 destroySemaphoreInfo = new DestroySemaphoreInfo(vi, semaphore);
95 flushInfo.fNumSemaphores = 1;
96 flushInfo.fSignalSemaphores = &backendSemaphore;
97 flushInfo.fFinishedProc = unref_semaphore;
98 flushInfo.fFinishedContext = destroySemaphoreInfo;
99 }
100 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
101 grContext->submit(GrSyncCpu::kNo);
102 int drawFenceFd = -1;
103 if (semaphore != VK_NULL_HANDLE) {
104 if (GrSemaphoresSubmitted::kYes == submitted) {
105 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
106 }
107 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
108 flushInfo.fFinishedProc(destroySemaphoreInfo);
109 }
110 base::unique_fd res(drawFenceFd);
111 return res;
112 }
113
114 } // namespace android::renderengine::skia
115