blob: d8549299608857c217ea064a30dd258e3e94e698 [file] [log] [blame]
Ian Elliott1f0911e2022-09-09 16:31:47 -06001/*
2 * Copyright 2022 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// #define LOG_NDEBUG 0
18#undef LOG_TAG
19#define LOG_TAG "RenderEngine"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21
22#include "SkiaVkRenderEngine.h"
23
Nolan Scobiefc125ec2024-03-11 20:08:27 -040024#include "compat/SkiaGpuContext.h"
25
Ian Elliott1f0911e2022-09-09 16:31:47 -060026#include <GrBackendSemaphore.h>
27#include <GrContextOptions.h>
Nolan Scobiefc125ec2024-03-11 20:08:27 -040028#include <GrDirectContext.h>
Kevin Lubick9f207082024-03-06 13:33:17 +000029#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
Kevin Lubick2fc49112023-10-13 13:10:48 +000030#include <include/gpu/ganesh/vk/GrVkDirectContext.h>
Nolan Scobiefc125ec2024-03-11 20:08:27 -040031#include <vk/GrVkExtensions.h>
32#include <vk/GrVkTypes.h>
Ian Elliott1f0911e2022-09-09 16:31:47 -060033
34#include <android-base/stringprintf.h>
35#include <gui/TraceUtils.h>
36#include <sync/sync.h>
37#include <utils/Trace.h>
38
Ian Elliott1f0911e2022-09-09 16:31:47 -060039#include <memory>
Nolan Scobie0f539a72024-01-29 10:49:10 -050040#include <string>
Ian Elliott1f0911e2022-09-09 16:31:47 -060041
42#include <vulkan/vulkan.h>
43#include "log/log_main.h"
44
45namespace android {
46namespace renderengine {
47
Nolan Scobief52ad202024-03-06 18:18:28 -050048static skia::VulkanInterface sVulkanInterface;
49static skia::VulkanInterface sProtectedContentVulkanInterface;
Ian Elliott1f0911e2022-09-09 16:31:47 -060050
51static void sSetupVulkanInterface() {
Nolan Scobief52ad202024-03-06 18:18:28 -050052 if (!sVulkanInterface.isInitialized()) {
53 sVulkanInterface.init(false /* no protected content */);
Ian Elliott1f0911e2022-09-09 16:31:47 -060054 // We will have to abort if non-protected VkDevice creation fails (then nothing works).
Nolan Scobief52ad202024-03-06 18:18:28 -050055 LOG_ALWAYS_FATAL_IF(!sVulkanInterface.isInitialized(),
Ian Elliott1f0911e2022-09-09 16:31:47 -060056 "Could not initialize Vulkan RenderEngine!");
57 }
Nolan Scobief52ad202024-03-06 18:18:28 -050058 if (!sProtectedContentVulkanInterface.isInitialized()) {
59 sProtectedContentVulkanInterface.init(true /* protected content */);
60 if (!sProtectedContentVulkanInterface.isInitialized()) {
Ian Elliott1f0911e2022-09-09 16:31:47 -060061 ALOGE("Could not initialize protected content Vulkan RenderEngine.");
62 }
63 }
64}
65
Leon Scroggins IIIf3369ed2024-02-16 17:52:42 -050066bool RenderEngine::canSupport(GraphicsApi graphicsApi) {
67 switch (graphicsApi) {
68 case GraphicsApi::GL:
69 return true;
70 case GraphicsApi::VK: {
Nolan Scobief52ad202024-03-06 18:18:28 -050071 if (!sVulkanInterface.isInitialized()) {
72 sVulkanInterface.init(false /* no protected content */);
Leon Scroggins IIIf3369ed2024-02-16 17:52:42 -050073 ALOGD("%s: initialized == %s.", __func__,
Nolan Scobief52ad202024-03-06 18:18:28 -050074 sVulkanInterface.isInitialized() ? "true" : "false");
Leon Scroggins IIIf3369ed2024-02-16 17:52:42 -050075 }
Nolan Scobief52ad202024-03-06 18:18:28 -050076 return sVulkanInterface.isInitialized();
Leon Scroggins IIIf3369ed2024-02-16 17:52:42 -050077 }
78 }
79}
80
Ian Elliott1f0911e2022-09-09 16:31:47 -060081namespace skia {
82
83using base::StringAppendF;
84
Ian Elliott1f0911e2022-09-09 16:31:47 -060085std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
86 const RenderEngineCreationArgs& args) {
87 std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
Nolan Scobiefc125ec2024-03-11 20:08:27 -040088 engine->ensureContextsCreated();
Ian Elliott1f0911e2022-09-09 16:31:47 -060089
Nolan Scobief52ad202024-03-06 18:18:28 -050090 if (sVulkanInterface.isInitialized()) {
Ian Elliott1f0911e2022-09-09 16:31:47 -060091 ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__);
92 return engine;
93 } else {
94 ALOGD("SkiaVkRenderEngine::%s: could not create SkiaVkRenderEngine. "
95 "Likely insufficient Vulkan support",
96 __func__);
97 return {};
98 }
99}
100
101SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
Leon Scroggins III696bf932024-01-24 15:21:05 -0500102 : SkiaRenderEngine(args.threaded, static_cast<PixelFormat>(args.pixelFormat),
Alec Mouri47bcb072023-08-15 02:02:49 +0000103 args.supportsBackgroundBlur) {}
Ian Elliott1f0911e2022-09-09 16:31:47 -0600104
105SkiaVkRenderEngine::~SkiaVkRenderEngine() {
106 finishRenderingAndAbandonContext();
107}
108
Nolan Scobiefc125ec2024-03-11 20:08:27 -0400109SkiaRenderEngine::Contexts SkiaVkRenderEngine::createContexts() {
Ian Elliott1f0911e2022-09-09 16:31:47 -0600110 sSetupVulkanInterface();
111
112 SkiaRenderEngine::Contexts contexts;
Nolan Scobiefc125ec2024-03-11 20:08:27 -0400113 contexts.first = SkiaGpuContext::MakeVulkan_Ganesh(sVulkanInterface.getGaneshBackendContext(),
114 mSkSLCacheMonitor);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600115 if (supportsProtectedContentImpl()) {
Nolan Scobiefc125ec2024-03-11 20:08:27 -0400116 contexts.second = SkiaGpuContext::MakeVulkan_Ganesh(sProtectedContentVulkanInterface
117 .getGaneshBackendContext(),
118 mSkSLCacheMonitor);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600119 }
120
121 return contexts;
122}
123
124bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
Nolan Scobief52ad202024-03-06 18:18:28 -0500125 return sProtectedContentVulkanInterface.isInitialized();
Ian Elliott1f0911e2022-09-09 16:31:47 -0600126}
127
128bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
129 return true;
130}
131
Nolan Scobief52ad202024-03-06 18:18:28 -0500132static void unref_semaphore(void* semaphore) {
133 SkiaVkRenderEngine::DestroySemaphoreInfo* info =
134 reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
135 info->unref();
Ian Elliott1f0911e2022-09-09 16:31:47 -0600136}
137
138static VulkanInterface& getVulkanInterface(bool protectedContext) {
139 if (protectedContext) {
140 return sProtectedContentVulkanInterface;
141 }
142 return sVulkanInterface;
143}
144
Nolan Scobiefc125ec2024-03-11 20:08:27 -0400145void SkiaVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
Ian Elliott1f0911e2022-09-09 16:31:47 -0600146 if (fenceFd.get() < 0) return;
147
148 int dupedFd = dup(fenceFd.get());
149 if (dupedFd < 0) {
150 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
151 sync_wait(fenceFd.get(), -1);
152 return;
153 }
154
155 base::unique_fd fenceDup(dupedFd);
156 VkSemaphore waitSemaphore =
157 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
Kevin Lubick9f207082024-03-06 13:33:17 +0000158 GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
Nolan Scobiefc125ec2024-03-11 20:08:27 -0400159 context->grDirectContext()->wait(1, &beSemaphore, true /* delete after wait */);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600160}
161
Nolan Scobiefc125ec2024-03-11 20:08:27 -0400162base::unique_fd SkiaVkRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
163 sk_sp<GrDirectContext> grContext = context->grDirectContext();
Ian Elliott98e87162023-04-14 14:05:19 -0600164 VulkanInterface& vi = getVulkanInterface(isProtected());
165 VkSemaphore semaphore = vi.createExportableSemaphore();
166
Kevin Lubick9f207082024-03-06 13:33:17 +0000167 GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
Ian Elliott98e87162023-04-14 14:05:19 -0600168
Ian Elliott1f0911e2022-09-09 16:31:47 -0600169 GrFlushInfo flushInfo;
Ian Elliott98e87162023-04-14 14:05:19 -0600170 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
171 if (semaphore != VK_NULL_HANDLE) {
Nolan Scobief52ad202024-03-06 18:18:28 -0500172 destroySemaphoreInfo = new DestroySemaphoreInfo(vi, semaphore);
Ian Elliott98e87162023-04-14 14:05:19 -0600173 flushInfo.fNumSemaphores = 1;
174 flushInfo.fSignalSemaphores = &backendSemaphore;
Nolan Scobief52ad202024-03-06 18:18:28 -0500175 flushInfo.fFinishedProc = unref_semaphore;
Ian Elliott98e87162023-04-14 14:05:19 -0600176 flushInfo.fFinishedContext = destroySemaphoreInfo;
177 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600178 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
Kevin Lubicka0efc342023-09-20 13:11:52 +0000179 grContext->submit(GrSyncCpu::kNo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600180 int drawFenceFd = -1;
Ian Elliott98e87162023-04-14 14:05:19 -0600181 if (semaphore != VK_NULL_HANDLE) {
182 if (GrSemaphoresSubmitted::kYes == submitted) {
183 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
184 }
185 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
186 flushInfo.fFinishedProc(destroySemaphoreInfo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600187 }
188 base::unique_fd res(drawFenceFd);
189 return res;
190}
191
192int SkiaVkRenderEngine::getContextPriority() {
193 // EGL_CONTEXT_PRIORITY_REALTIME_NV
194 constexpr int kRealtimePriority = 0x3357;
Nolan Scobief52ad202024-03-06 18:18:28 -0500195 if (getVulkanInterface(isProtected()).isRealtimePriority()) {
Ian Elliott1f0911e2022-09-09 16:31:47 -0600196 return kRealtimePriority;
197 } else {
198 return 0;
199 }
200}
201
202void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
203 StringAppendF(&result, "\n ------------RE Vulkan----------\n");
Nolan Scobief52ad202024-03-06 18:18:28 -0500204 StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.isInitialized());
Ian Elliott1f0911e2022-09-09 16:31:47 -0600205 StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
Nolan Scobief52ad202024-03-06 18:18:28 -0500206 sProtectedContentVulkanInterface.isInitialized());
Ian Elliott1f0911e2022-09-09 16:31:47 -0600207
Nolan Scobief52ad202024-03-06 18:18:28 -0500208 if (!sVulkanInterface.isInitialized()) {
Ian Elliott1f0911e2022-09-09 16:31:47 -0600209 return;
210 }
211
212 StringAppendF(&result, "\n Instance extensions:\n");
Nolan Scobief52ad202024-03-06 18:18:28 -0500213 for (const auto& name : sVulkanInterface.getInstanceExtensionNames()) {
Ian Elliott1f0911e2022-09-09 16:31:47 -0600214 StringAppendF(&result, "\n %s\n", name.c_str());
215 }
216
217 StringAppendF(&result, "\n Device extensions:\n");
Nolan Scobief52ad202024-03-06 18:18:28 -0500218 for (const auto& name : sVulkanInterface.getDeviceExtensionNames()) {
Ian Elliott1f0911e2022-09-09 16:31:47 -0600219 StringAppendF(&result, "\n %s\n", name.c_str());
220 }
221}
222
223} // namespace skia
224} // namespace renderengine
225} // namespace android