xref: /aosp_15_r20/frameworks/native/libs/renderengine/skia/SkiaVkRenderEngine.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2022 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 // #define LOG_NDEBUG 0
18*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
19*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "RenderEngine"
20*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker #include "SkiaVkRenderEngine.h"
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include "GaneshVkRenderEngine.h"
25*38e8c45fSAndroid Build Coastguard Worker #include "compat/SkiaGpuContext.h"
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/ganesh/GrBackendSemaphore.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/ganesh/GrContextOptions.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/ganesh/GrDirectContext.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/ganesh/vk/GrVkDirectContext.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <include/gpu/ganesh/vk/GrVkTypes.h>
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <common/trace.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <sync/sync.h>
37*38e8c45fSAndroid Build Coastguard Worker 
38*38e8c45fSAndroid Build Coastguard Worker #include <memory>
39*38e8c45fSAndroid Build Coastguard Worker #include <string>
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker #include <vulkan/vulkan.h>
42*38e8c45fSAndroid Build Coastguard Worker #include "log/log_main.h"
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker namespace android {
45*38e8c45fSAndroid Build Coastguard Worker namespace renderengine {
46*38e8c45fSAndroid Build Coastguard Worker 
47*38e8c45fSAndroid Build Coastguard Worker static skia::VulkanInterface sVulkanInterface;
48*38e8c45fSAndroid Build Coastguard Worker static skia::VulkanInterface sProtectedContentVulkanInterface;
49*38e8c45fSAndroid Build Coastguard Worker 
sSetupVulkanInterface()50*38e8c45fSAndroid Build Coastguard Worker static void sSetupVulkanInterface() {
51*38e8c45fSAndroid Build Coastguard Worker     if (!sVulkanInterface.isInitialized()) {
52*38e8c45fSAndroid Build Coastguard Worker         sVulkanInterface.init(false /* no protected content */);
53*38e8c45fSAndroid Build Coastguard Worker         // We will have to abort if non-protected VkDevice creation fails (then nothing works).
54*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(!sVulkanInterface.isInitialized(),
55*38e8c45fSAndroid Build Coastguard Worker                             "Could not initialize Vulkan RenderEngine!");
56*38e8c45fSAndroid Build Coastguard Worker     }
57*38e8c45fSAndroid Build Coastguard Worker     if (!sProtectedContentVulkanInterface.isInitialized()) {
58*38e8c45fSAndroid Build Coastguard Worker         sProtectedContentVulkanInterface.init(true /* protected content */);
59*38e8c45fSAndroid Build Coastguard Worker         if (!sProtectedContentVulkanInterface.isInitialized()) {
60*38e8c45fSAndroid Build Coastguard Worker             ALOGE("Could not initialize protected content Vulkan RenderEngine.");
61*38e8c45fSAndroid Build Coastguard Worker         }
62*38e8c45fSAndroid Build Coastguard Worker     }
63*38e8c45fSAndroid Build Coastguard Worker }
64*38e8c45fSAndroid Build Coastguard Worker 
canSupport(GraphicsApi graphicsApi)65*38e8c45fSAndroid Build Coastguard Worker bool RenderEngine::canSupport(GraphicsApi graphicsApi) {
66*38e8c45fSAndroid Build Coastguard Worker     switch (graphicsApi) {
67*38e8c45fSAndroid Build Coastguard Worker         case GraphicsApi::GL:
68*38e8c45fSAndroid Build Coastguard Worker             return true;
69*38e8c45fSAndroid Build Coastguard Worker         case GraphicsApi::VK: {
70*38e8c45fSAndroid Build Coastguard Worker             // Static local variables are initialized once, on first invocation of the function.
71*38e8c45fSAndroid Build Coastguard Worker             static const bool canSupportVulkan = []() {
72*38e8c45fSAndroid Build Coastguard Worker                 if (!sVulkanInterface.isInitialized()) {
73*38e8c45fSAndroid Build Coastguard Worker                     sVulkanInterface.init(false /* no protected content */);
74*38e8c45fSAndroid Build Coastguard Worker                     ALOGD("%s: initialized == %s.", __func__,
75*38e8c45fSAndroid Build Coastguard Worker                           sVulkanInterface.isInitialized() ? "true" : "false");
76*38e8c45fSAndroid Build Coastguard Worker                     if (!sVulkanInterface.isInitialized()) {
77*38e8c45fSAndroid Build Coastguard Worker                         sVulkanInterface.teardown();
78*38e8c45fSAndroid Build Coastguard Worker                         return false;
79*38e8c45fSAndroid Build Coastguard Worker                     }
80*38e8c45fSAndroid Build Coastguard Worker                 }
81*38e8c45fSAndroid Build Coastguard Worker                 return true;
82*38e8c45fSAndroid Build Coastguard Worker             }();
83*38e8c45fSAndroid Build Coastguard Worker             return canSupportVulkan;
84*38e8c45fSAndroid Build Coastguard Worker         }
85*38e8c45fSAndroid Build Coastguard Worker     }
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker 
teardown(GraphicsApi graphicsApi)88*38e8c45fSAndroid Build Coastguard Worker void RenderEngine::teardown(GraphicsApi graphicsApi) {
89*38e8c45fSAndroid Build Coastguard Worker     switch (graphicsApi) {
90*38e8c45fSAndroid Build Coastguard Worker         case GraphicsApi::GL:
91*38e8c45fSAndroid Build Coastguard Worker             break;
92*38e8c45fSAndroid Build Coastguard Worker         case GraphicsApi::VK: {
93*38e8c45fSAndroid Build Coastguard Worker             if (sVulkanInterface.isInitialized()) {
94*38e8c45fSAndroid Build Coastguard Worker                 sVulkanInterface.teardown();
95*38e8c45fSAndroid Build Coastguard Worker                 ALOGD("Tearing down the unprotected VulkanInterface.");
96*38e8c45fSAndroid Build Coastguard Worker             }
97*38e8c45fSAndroid Build Coastguard Worker             if (sProtectedContentVulkanInterface.isInitialized()) {
98*38e8c45fSAndroid Build Coastguard Worker                 sProtectedContentVulkanInterface.teardown();
99*38e8c45fSAndroid Build Coastguard Worker                 ALOGD("Tearing down the protected VulkanInterface.");
100*38e8c45fSAndroid Build Coastguard Worker             }
101*38e8c45fSAndroid Build Coastguard Worker             break;
102*38e8c45fSAndroid Build Coastguard Worker         }
103*38e8c45fSAndroid Build Coastguard Worker     }
104*38e8c45fSAndroid Build Coastguard Worker }
105*38e8c45fSAndroid Build Coastguard Worker 
106*38e8c45fSAndroid Build Coastguard Worker namespace skia {
107*38e8c45fSAndroid Build Coastguard Worker 
108*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
109*38e8c45fSAndroid Build Coastguard Worker 
SkiaVkRenderEngine(const RenderEngineCreationArgs & args)110*38e8c45fSAndroid Build Coastguard Worker SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
111*38e8c45fSAndroid Build Coastguard Worker       : SkiaRenderEngine(args.threaded, static_cast<PixelFormat>(args.pixelFormat),
112*38e8c45fSAndroid Build Coastguard Worker                          args.blurAlgorithm) {}
113*38e8c45fSAndroid Build Coastguard Worker 
~SkiaVkRenderEngine()114*38e8c45fSAndroid Build Coastguard Worker SkiaVkRenderEngine::~SkiaVkRenderEngine() {
115*38e8c45fSAndroid Build Coastguard Worker     finishRenderingAndAbandonContexts();
116*38e8c45fSAndroid Build Coastguard Worker     // Teardown VulkanInterfaces after Skia contexts have been abandoned
117*38e8c45fSAndroid Build Coastguard Worker     teardown(GraphicsApi::VK);
118*38e8c45fSAndroid Build Coastguard Worker }
119*38e8c45fSAndroid Build Coastguard Worker 
createContexts()120*38e8c45fSAndroid Build Coastguard Worker SkiaRenderEngine::Contexts SkiaVkRenderEngine::createContexts() {
121*38e8c45fSAndroid Build Coastguard Worker     sSetupVulkanInterface();
122*38e8c45fSAndroid Build Coastguard Worker     // More work would need to be done in order to have multiple RenderEngine instances. In
123*38e8c45fSAndroid Build Coastguard Worker     // particular, they would not be able to share the same VulkanInterface(s).
124*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(!sVulkanInterface.takeOwnership(),
125*38e8c45fSAndroid Build Coastguard Worker                         "SkiaVkRenderEngine couldn't take ownership of existing unprotected "
126*38e8c45fSAndroid Build Coastguard Worker                         "VulkanInterface! Only one SkiaVkRenderEngine instance may exist at a "
127*38e8c45fSAndroid Build Coastguard Worker                         "time.");
128*38e8c45fSAndroid Build Coastguard Worker     if (sProtectedContentVulkanInterface.isInitialized()) {
129*38e8c45fSAndroid Build Coastguard Worker         // takeOwnership fails on an uninitialized VulkanInterface, but protected content support is
130*38e8c45fSAndroid Build Coastguard Worker         // optional.
131*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(!sProtectedContentVulkanInterface.takeOwnership(),
132*38e8c45fSAndroid Build Coastguard Worker                             "SkiaVkRenderEngine couldn't take ownership of existing protected "
133*38e8c45fSAndroid Build Coastguard Worker                             "VulkanInterface! Only one SkiaVkRenderEngine instance may exist at a "
134*38e8c45fSAndroid Build Coastguard Worker                             "time.");
135*38e8c45fSAndroid Build Coastguard Worker     }
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker     SkiaRenderEngine::Contexts contexts;
138*38e8c45fSAndroid Build Coastguard Worker     contexts.first = createContext(sVulkanInterface);
139*38e8c45fSAndroid Build Coastguard Worker     if (supportsProtectedContentImpl()) {
140*38e8c45fSAndroid Build Coastguard Worker         contexts.second = createContext(sProtectedContentVulkanInterface);
141*38e8c45fSAndroid Build Coastguard Worker     }
142*38e8c45fSAndroid Build Coastguard Worker 
143*38e8c45fSAndroid Build Coastguard Worker     return contexts;
144*38e8c45fSAndroid Build Coastguard Worker }
145*38e8c45fSAndroid Build Coastguard Worker 
supportsProtectedContentImpl() const146*38e8c45fSAndroid Build Coastguard Worker bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
147*38e8c45fSAndroid Build Coastguard Worker     return sProtectedContentVulkanInterface.isInitialized();
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker 
useProtectedContextImpl(GrProtected)150*38e8c45fSAndroid Build Coastguard Worker bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
151*38e8c45fSAndroid Build Coastguard Worker     return true;
152*38e8c45fSAndroid Build Coastguard Worker }
153*38e8c45fSAndroid Build Coastguard Worker 
getVulkanInterface(bool protectedContext)154*38e8c45fSAndroid Build Coastguard Worker VulkanInterface& SkiaVkRenderEngine::getVulkanInterface(bool protectedContext) {
155*38e8c45fSAndroid Build Coastguard Worker     if (protectedContext) {
156*38e8c45fSAndroid Build Coastguard Worker         return sProtectedContentVulkanInterface;
157*38e8c45fSAndroid Build Coastguard Worker     }
158*38e8c45fSAndroid Build Coastguard Worker     return sVulkanInterface;
159*38e8c45fSAndroid Build Coastguard Worker }
160*38e8c45fSAndroid Build Coastguard Worker 
getContextPriority()161*38e8c45fSAndroid Build Coastguard Worker int SkiaVkRenderEngine::getContextPriority() {
162*38e8c45fSAndroid Build Coastguard Worker     // EGL_CONTEXT_PRIORITY_REALTIME_NV
163*38e8c45fSAndroid Build Coastguard Worker     constexpr int kRealtimePriority = 0x3357;
164*38e8c45fSAndroid Build Coastguard Worker     if (getVulkanInterface(isProtected()).isRealtimePriority()) {
165*38e8c45fSAndroid Build Coastguard Worker         return kRealtimePriority;
166*38e8c45fSAndroid Build Coastguard Worker     } else {
167*38e8c45fSAndroid Build Coastguard Worker         return 0;
168*38e8c45fSAndroid Build Coastguard Worker     }
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker 
appendBackendSpecificInfoToDump(std::string & result)171*38e8c45fSAndroid Build Coastguard Worker void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
172*38e8c45fSAndroid Build Coastguard Worker     // Subclasses will prepend a backend-specific name / section header
173*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result, "Vulkan device initialized: %d\n", sVulkanInterface.isInitialized());
174*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result, "Vulkan protected device initialized: %d\n",
175*38e8c45fSAndroid Build Coastguard Worker                   sProtectedContentVulkanInterface.isInitialized());
176*38e8c45fSAndroid Build Coastguard Worker 
177*38e8c45fSAndroid Build Coastguard Worker     if (!sVulkanInterface.isInitialized()) {
178*38e8c45fSAndroid Build Coastguard Worker         return;
179*38e8c45fSAndroid Build Coastguard Worker     }
180*38e8c45fSAndroid Build Coastguard Worker 
181*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result, "Instance extensions: [\n");
182*38e8c45fSAndroid Build Coastguard Worker     for (const auto& name : sVulkanInterface.getInstanceExtensionNames()) {
183*38e8c45fSAndroid Build Coastguard Worker         StringAppendF(&result, "  %s\n", name.c_str());
184*38e8c45fSAndroid Build Coastguard Worker     }
185*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result, "]\n");
186*38e8c45fSAndroid Build Coastguard Worker 
187*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result, "Device extensions: [\n");
188*38e8c45fSAndroid Build Coastguard Worker     for (const auto& name : sVulkanInterface.getDeviceExtensionNames()) {
189*38e8c45fSAndroid Build Coastguard Worker         StringAppendF(&result, "  %s\n", name.c_str());
190*38e8c45fSAndroid Build Coastguard Worker     }
191*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result, "]\n");
192*38e8c45fSAndroid Build Coastguard Worker }
193*38e8c45fSAndroid Build Coastguard Worker 
194*38e8c45fSAndroid Build Coastguard Worker } // namespace skia
195*38e8c45fSAndroid Build Coastguard Worker } // namespace renderengine
196*38e8c45fSAndroid Build Coastguard Worker } // namespace android
197