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