1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2024 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include "GraphiteVkRenderEngine.h"
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
20*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "RenderEngine"
21*38e8c45fSAndroid Build Coastguard Worker
22*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/GpuTypes.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/graphite/BackendSemaphore.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/graphite/Context.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/graphite/Recording.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/graphite/vk/VulkanGraphiteTypes.h>
27*38e8c45fSAndroid Build Coastguard Worker
28*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <log/log_main.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <sync/sync.h>
31*38e8c45fSAndroid Build Coastguard Worker
32*38e8c45fSAndroid Build Coastguard Worker #include <memory>
33*38e8c45fSAndroid Build Coastguard Worker #include <vector>
34*38e8c45fSAndroid Build Coastguard Worker
35*38e8c45fSAndroid Build Coastguard Worker namespace android::renderengine::skia {
36*38e8c45fSAndroid Build Coastguard Worker
37*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
38*38e8c45fSAndroid Build Coastguard Worker
create(const RenderEngineCreationArgs & args)39*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<GraphiteVkRenderEngine> GraphiteVkRenderEngine::create(
40*38e8c45fSAndroid Build Coastguard Worker const RenderEngineCreationArgs& args) {
41*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<GraphiteVkRenderEngine> engine(new GraphiteVkRenderEngine(args));
42*38e8c45fSAndroid Build Coastguard Worker engine->ensureContextsCreated();
43*38e8c45fSAndroid Build Coastguard Worker
44*38e8c45fSAndroid Build Coastguard Worker if (getVulkanInterface(false).isInitialized()) {
45*38e8c45fSAndroid Build Coastguard Worker ALOGD("GraphiteVkRenderEngine::%s: successfully initialized GraphiteVkRenderEngine",
46*38e8c45fSAndroid Build Coastguard Worker __func__);
47*38e8c45fSAndroid Build Coastguard Worker return engine;
48*38e8c45fSAndroid Build Coastguard Worker } else {
49*38e8c45fSAndroid Build Coastguard Worker ALOGE("GraphiteVkRenderEngine::%s: could not create GraphiteVkRenderEngine. "
50*38e8c45fSAndroid Build Coastguard Worker "Likely insufficient Vulkan support",
51*38e8c45fSAndroid Build Coastguard Worker __func__);
52*38e8c45fSAndroid Build Coastguard Worker return {};
53*38e8c45fSAndroid Build Coastguard Worker }
54*38e8c45fSAndroid Build Coastguard Worker }
55*38e8c45fSAndroid Build Coastguard Worker
56*38e8c45fSAndroid Build Coastguard Worker // Graphite-specific function signature for fFinishedProc callback.
unref_semaphore(void * semaphore,skgpu::CallbackResult result)57*38e8c45fSAndroid Build Coastguard Worker static void unref_semaphore(void* semaphore, skgpu::CallbackResult result) {
58*38e8c45fSAndroid Build Coastguard Worker if (result != skgpu::CallbackResult::kSuccess) {
59*38e8c45fSAndroid Build Coastguard Worker ALOGE("Graphite submission of work to GPU failed, check for Skia errors");
60*38e8c45fSAndroid Build Coastguard Worker }
61*38e8c45fSAndroid Build Coastguard Worker SkiaVkRenderEngine::DestroySemaphoreInfo* info =
62*38e8c45fSAndroid Build Coastguard Worker reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
63*38e8c45fSAndroid Build Coastguard Worker info->unref();
64*38e8c45fSAndroid Build Coastguard Worker }
65*38e8c45fSAndroid Build Coastguard Worker
createContext(VulkanInterface & vulkanInterface)66*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<SkiaGpuContext> GraphiteVkRenderEngine::createContext(
67*38e8c45fSAndroid Build Coastguard Worker VulkanInterface& vulkanInterface) {
68*38e8c45fSAndroid Build Coastguard Worker return SkiaGpuContext::MakeVulkan_Graphite(vulkanInterface.getGraphiteBackendContext());
69*38e8c45fSAndroid Build Coastguard Worker }
70*38e8c45fSAndroid Build Coastguard Worker
waitFence(SkiaGpuContext *,base::borrowed_fd fenceFd)71*38e8c45fSAndroid Build Coastguard Worker void GraphiteVkRenderEngine::waitFence(SkiaGpuContext*, base::borrowed_fd fenceFd) {
72*38e8c45fSAndroid Build Coastguard Worker if (fenceFd.get() < 0) return;
73*38e8c45fSAndroid Build Coastguard Worker
74*38e8c45fSAndroid Build Coastguard Worker int dupedFd = dup(fenceFd.get());
75*38e8c45fSAndroid Build Coastguard Worker if (dupedFd < 0) {
76*38e8c45fSAndroid Build Coastguard Worker ALOGE("failed to create duplicate fence fd: %d", dupedFd);
77*38e8c45fSAndroid Build Coastguard Worker sync_wait(fenceFd.get(), -1);
78*38e8c45fSAndroid Build Coastguard Worker return;
79*38e8c45fSAndroid Build Coastguard Worker }
80*38e8c45fSAndroid Build Coastguard Worker
81*38e8c45fSAndroid Build Coastguard Worker base::unique_fd fenceDup(dupedFd);
82*38e8c45fSAndroid Build Coastguard Worker VkSemaphore waitSemaphore =
83*38e8c45fSAndroid Build Coastguard Worker getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
84*38e8c45fSAndroid Build Coastguard Worker auto beSemaphore = graphite::BackendSemaphores::MakeVulkan(waitSemaphore);
85*38e8c45fSAndroid Build Coastguard Worker mStagedWaitSemaphores.push_back(beSemaphore);
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker
flushAndSubmit(SkiaGpuContext * context,sk_sp<SkSurface>)88*38e8c45fSAndroid Build Coastguard Worker base::unique_fd GraphiteVkRenderEngine::flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface>) {
89*38e8c45fSAndroid Build Coastguard Worker // Minimal Recording setup. Required even if there are no incoming semaphores to wait on, and if
90*38e8c45fSAndroid Build Coastguard Worker // creating the outgoing signaling semaphore fails.
91*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<graphite::Recording> recording = context->graphiteRecorder()->snap();
92*38e8c45fSAndroid Build Coastguard Worker graphite::InsertRecordingInfo insertInfo;
93*38e8c45fSAndroid Build Coastguard Worker insertInfo.fRecording = recording.get();
94*38e8c45fSAndroid Build Coastguard Worker
95*38e8c45fSAndroid Build Coastguard Worker VulkanInterface& vulkanInterface = getVulkanInterface(isProtected());
96*38e8c45fSAndroid Build Coastguard Worker // This "signal" semaphore is called after rendering, but it is cleaned up in the same mechanism
97*38e8c45fSAndroid Build Coastguard Worker // as "wait" semaphores from waitFence.
98*38e8c45fSAndroid Build Coastguard Worker VkSemaphore vkSignalSemaphore = vulkanInterface.createExportableSemaphore();
99*38e8c45fSAndroid Build Coastguard Worker auto backendSignalSemaphore = graphite::BackendSemaphores::MakeVulkan(vkSignalSemaphore);
100*38e8c45fSAndroid Build Coastguard Worker
101*38e8c45fSAndroid Build Coastguard Worker // Collect all Vk semaphores that DestroySemaphoreInfo needs to own and delete after GPU work.
102*38e8c45fSAndroid Build Coastguard Worker std::vector<VkSemaphore> vkSemaphoresToCleanUp;
103*38e8c45fSAndroid Build Coastguard Worker if (vkSignalSemaphore != VK_NULL_HANDLE) {
104*38e8c45fSAndroid Build Coastguard Worker vkSemaphoresToCleanUp.push_back(vkSignalSemaphore);
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker for (auto backendWaitSemaphore : mStagedWaitSemaphores) {
107*38e8c45fSAndroid Build Coastguard Worker vkSemaphoresToCleanUp.push_back(
108*38e8c45fSAndroid Build Coastguard Worker graphite::BackendSemaphores::GetVkSemaphore(backendWaitSemaphore));
109*38e8c45fSAndroid Build Coastguard Worker }
110*38e8c45fSAndroid Build Coastguard Worker
111*38e8c45fSAndroid Build Coastguard Worker DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
112*38e8c45fSAndroid Build Coastguard Worker if (vkSemaphoresToCleanUp.size() > 0) {
113*38e8c45fSAndroid Build Coastguard Worker destroySemaphoreInfo =
114*38e8c45fSAndroid Build Coastguard Worker new DestroySemaphoreInfo(vulkanInterface, std::move(vkSemaphoresToCleanUp));
115*38e8c45fSAndroid Build Coastguard Worker
116*38e8c45fSAndroid Build Coastguard Worker insertInfo.fNumWaitSemaphores = mStagedWaitSemaphores.size();
117*38e8c45fSAndroid Build Coastguard Worker insertInfo.fWaitSemaphores = mStagedWaitSemaphores.data();
118*38e8c45fSAndroid Build Coastguard Worker insertInfo.fNumSignalSemaphores = 1;
119*38e8c45fSAndroid Build Coastguard Worker insertInfo.fSignalSemaphores = &backendSignalSemaphore;
120*38e8c45fSAndroid Build Coastguard Worker insertInfo.fFinishedProc = unref_semaphore;
121*38e8c45fSAndroid Build Coastguard Worker insertInfo.fFinishedContext = destroySemaphoreInfo;
122*38e8c45fSAndroid Build Coastguard Worker }
123*38e8c45fSAndroid Build Coastguard Worker
124*38e8c45fSAndroid Build Coastguard Worker const bool inserted = context->graphiteContext()->insertRecording(insertInfo);
125*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!inserted,
126*38e8c45fSAndroid Build Coastguard Worker "graphite::Context::insertRecording(...) failed, check for Skia errors");
127*38e8c45fSAndroid Build Coastguard Worker const bool submitted = context->graphiteContext()->submit(graphite::SyncToCpu::kNo);
128*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!submitted, "graphite::Context::submit(...) failed, check for Skia errors");
129*38e8c45fSAndroid Build Coastguard Worker // Skia's "backend" semaphores can be deleted immediately after inserting the recording; only
130*38e8c45fSAndroid Build Coastguard Worker // the underlying VK semaphores need to be kept until GPU work is complete.
131*38e8c45fSAndroid Build Coastguard Worker mStagedWaitSemaphores.clear();
132*38e8c45fSAndroid Build Coastguard Worker
133*38e8c45fSAndroid Build Coastguard Worker base::unique_fd drawFenceFd(-1);
134*38e8c45fSAndroid Build Coastguard Worker if (vkSignalSemaphore != VK_NULL_HANDLE) {
135*38e8c45fSAndroid Build Coastguard Worker drawFenceFd.reset(vulkanInterface.exportSemaphoreSyncFd(vkSignalSemaphore));
136*38e8c45fSAndroid Build Coastguard Worker }
137*38e8c45fSAndroid Build Coastguard Worker // Now that drawFenceFd has been created, we can delete RE's reference to this semaphore, as
138*38e8c45fSAndroid Build Coastguard Worker // another reference is still held until fFinishedProc is called after completion of GPU work.
139*38e8c45fSAndroid Build Coastguard Worker if (destroySemaphoreInfo) {
140*38e8c45fSAndroid Build Coastguard Worker destroySemaphoreInfo->unref();
141*38e8c45fSAndroid Build Coastguard Worker }
142*38e8c45fSAndroid Build Coastguard Worker return drawFenceFd;
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker
appendBackendSpecificInfoToDump(std::string & result)145*38e8c45fSAndroid Build Coastguard Worker void GraphiteVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
146*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result, "\n ------------RE Vulkan (Graphite)----------\n");
147*38e8c45fSAndroid Build Coastguard Worker SkiaVkRenderEngine::appendBackendSpecificInfoToDump(result);
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker
150*38e8c45fSAndroid Build Coastguard Worker } // namespace android::renderengine::skia
151