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 <android-base/stringprintf.h>
25 #include <common/trace.h>
26 #include <log/log_main.h>
27 #include <sync/sync.h>
28
29 namespace android::renderengine::skia {
30
31 using base::StringAppendF;
32
create(const RenderEngineCreationArgs & args)33 std::unique_ptr<GaneshVkRenderEngine> GaneshVkRenderEngine::create(
34 const RenderEngineCreationArgs& args) {
35 std::unique_ptr<GaneshVkRenderEngine> engine(new GaneshVkRenderEngine(args));
36 engine->ensureContextsCreated();
37
38 if (getVulkanInterface(false).isInitialized()) {
39 ALOGD("GaneshVkRenderEngine::%s: successfully initialized GaneshVkRenderEngine", __func__);
40 return engine;
41 } else {
42 ALOGE("GaneshVkRenderEngine::%s: could not create GaneshVkRenderEngine. "
43 "Likely insufficient Vulkan support",
44 __func__);
45 return {};
46 }
47 }
48
49 // Ganesh-specific function signature for fFinishedProc callback.
unref_semaphore(void * semaphore)50 static void unref_semaphore(void* semaphore) {
51 SkiaVkRenderEngine::DestroySemaphoreInfo* info =
52 reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
53 info->unref();
54 }
55
createContext(VulkanInterface & vulkanInterface)56 std::unique_ptr<SkiaGpuContext> GaneshVkRenderEngine::createContext(
57 VulkanInterface& vulkanInterface) {
58 return SkiaGpuContext::MakeVulkan_Ganesh(vulkanInterface.getGaneshBackendContext(),
59 mSkSLCacheMonitor);
60 }
61
waitFence(SkiaGpuContext * context,base::borrowed_fd fenceFd)62 void GaneshVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
63 if (fenceFd.get() < 0) return;
64
65 const int dupedFd = dup(fenceFd.get());
66 if (dupedFd < 0) {
67 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
68 sync_wait(fenceFd.get(), -1);
69 return;
70 }
71
72 base::unique_fd fenceDup(dupedFd);
73 VkSemaphore waitSemaphore =
74 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
75 GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
76 constexpr bool kDeleteAfterWait = true;
77 context->grDirectContext()->wait(1, &beSemaphore, kDeleteAfterWait);
78 }
79
flushAndSubmit(SkiaGpuContext * context,sk_sp<SkSurface> dstSurface)80 base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context,
81 sk_sp<SkSurface> dstSurface) {
82 sk_sp<GrDirectContext> grContext = context->grDirectContext();
83 {
84 SFTRACE_NAME("flush surface");
85 // TODO: Investigate feasibility of combining this "surface flush" into the "context flush"
86 // below.
87 context->grDirectContext()->flush(dstSurface.get());
88 }
89
90 VulkanInterface& vi = getVulkanInterface(isProtected());
91 VkSemaphore semaphore = vi.createExportableSemaphore();
92 GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
93
94 GrFlushInfo flushInfo;
95 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
96 if (semaphore != VK_NULL_HANDLE) {
97 destroySemaphoreInfo = new DestroySemaphoreInfo(vi, semaphore);
98 flushInfo.fNumSemaphores = 1;
99 flushInfo.fSignalSemaphores = &backendSemaphore;
100 flushInfo.fFinishedProc = unref_semaphore;
101 flushInfo.fFinishedContext = destroySemaphoreInfo;
102 }
103 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
104 grContext->submit(GrSyncCpu::kNo);
105 int drawFenceFd = -1;
106 if (semaphore != VK_NULL_HANDLE) {
107 if (GrSemaphoresSubmitted::kYes == submitted) {
108 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
109 }
110 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
111 flushInfo.fFinishedProc(destroySemaphoreInfo);
112 }
113 base::unique_fd res(drawFenceFd);
114 return res;
115 }
116
appendBackendSpecificInfoToDump(std::string & result)117 void GaneshVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
118 StringAppendF(&result, "\n ------------RE Vulkan (Ganesh)----------\n");
119 SkiaVkRenderEngine::appendBackendSpecificInfoToDump(result);
120 }
121
122 } // namespace android::renderengine::skia
123