Have GrContext hold a strong ref to VulkanManager
VulkanManager is already ref counted and can be reused across GrContext's thanks to being shared with HardwareBitmapUploader. So take advantage of this + the newly added skia API for GrContext being destroyed to have GrContext hold a strong ref to VulkanManager which in turn keeps the VkDevice alive. If somehow we never recover from this we'll just keep using the initial device when creating the next Grcontext which should be fine. Memory usage will be sub-optimal but that's better than crashing probably. Bug: 266626090 Test: unable to repro bug issue, so speculative fix + it didn't get worse at least? Change-Id: I2038dacea679c29fd098462d4cf9d298e1215fb2
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "Layer.h"
|
||||
#include "Properties.h"
|
||||
#include "RenderThread.h"
|
||||
#include "VulkanManager.h"
|
||||
#include "pipeline/skia/ATraceMemoryDump.h"
|
||||
#include "pipeline/skia/ShaderCache.h"
|
||||
#include "pipeline/skia/SkiaMemoryTracer.h"
|
||||
@@ -182,8 +183,14 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
|
||||
}
|
||||
log.appendFormat("Contexts: %zu (stopped = %zu)\n", mCanvasContexts.size(), stoppedContexts);
|
||||
|
||||
auto vkInstance = VulkanManager::peekInstance();
|
||||
if (!mGrContext) {
|
||||
log.appendFormat("No GPU context.\n");
|
||||
if (!vkInstance) {
|
||||
log.appendFormat("No GPU context.\n");
|
||||
} else {
|
||||
log.appendFormat("No GrContext; however %d remaining Vulkan refs",
|
||||
vkInstance->getStrongCount() - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::vector<skiapipeline::ResourcePair> cpuResourceMap = {
|
||||
|
||||
@@ -106,11 +106,11 @@ GrVkGetProc VulkanManager::sSkiaGetProp = [](const char* proc_name, VkInstance i
|
||||
#define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
|
||||
#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
|
||||
|
||||
sp<VulkanManager> VulkanManager::getInstance() {
|
||||
// cache a weakptr to the context to enable a second thread to share the same vulkan state
|
||||
static wp<VulkanManager> sWeakInstance = nullptr;
|
||||
static std::mutex sLock;
|
||||
// cache a weakptr to the context to enable a second thread to share the same vulkan state
|
||||
static wp<VulkanManager> sWeakInstance = nullptr;
|
||||
static std::mutex sLock;
|
||||
|
||||
sp<VulkanManager> VulkanManager::getInstance() {
|
||||
std::lock_guard _lock{sLock};
|
||||
sp<VulkanManager> vulkanManager = sWeakInstance.promote();
|
||||
if (!vulkanManager.get()) {
|
||||
@@ -121,6 +121,11 @@ sp<VulkanManager> VulkanManager::getInstance() {
|
||||
return vulkanManager;
|
||||
}
|
||||
|
||||
sp<VulkanManager> VulkanManager::peekInstance() {
|
||||
std::lock_guard _lock{sLock};
|
||||
return sWeakInstance.promote();
|
||||
}
|
||||
|
||||
VulkanManager::~VulkanManager() {
|
||||
if (mDevice != VK_NULL_HANDLE) {
|
||||
mDeviceWaitIdle(mDevice);
|
||||
@@ -403,9 +408,13 @@ void VulkanManager::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& options,
|
||||
ContextType contextType) {
|
||||
static void onGrContextReleased(void* context) {
|
||||
VulkanManager* manager = (VulkanManager*)context;
|
||||
manager->decStrong((void*)onGrContextReleased);
|
||||
}
|
||||
|
||||
sk_sp<GrDirectContext> VulkanManager::createContext(GrContextOptions& options,
|
||||
ContextType contextType) {
|
||||
GrVkBackendContext backendContext;
|
||||
backendContext.fInstance = mInstance;
|
||||
backendContext.fPhysicalDevice = mPhysicalDevice;
|
||||
@@ -417,6 +426,11 @@ sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& opti
|
||||
backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
|
||||
backendContext.fGetProc = sSkiaGetProp;
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(options.fContextDeleteProc != nullptr, "Conflicting fContextDeleteProcs!");
|
||||
this->incStrong((void*)onGrContextReleased);
|
||||
options.fContextDeleteContext = this;
|
||||
options.fContextDeleteProc = onGrContextReleased;
|
||||
|
||||
return GrDirectContext::MakeVulkan(backendContext, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ class RenderThread;
|
||||
class VulkanManager final : public RefBase {
|
||||
public:
|
||||
static sp<VulkanManager> getInstance();
|
||||
static sp<VulkanManager> peekInstance();
|
||||
|
||||
// Sets up the vulkan context that is shared amonst all clients of the VulkanManager. This must
|
||||
// be call once before use of the VulkanManager. Multiple calls after the first will simiply
|
||||
@@ -109,7 +110,7 @@ public:
|
||||
};
|
||||
|
||||
// returns a Skia graphic context used to draw content on the specified thread
|
||||
sk_sp<GrDirectContext> createContext(const GrContextOptions& options,
|
||||
sk_sp<GrDirectContext> createContext(GrContextOptions& options,
|
||||
ContextType contextType = ContextType::kRenderThread);
|
||||
|
||||
uint32_t getDriverVersion() const { return mDriverVersion; }
|
||||
|
||||
Reference in New Issue
Block a user