diff --git a/m133/BUILD.gn b/m133/BUILD.gn index 5e6c936b48557d8e19996fbc89060c6b30d8079b..51df52d86c9cfae409906303d83587e7d53e622d 100644 --- a/m133/BUILD.gn +++ b/m133/BUILD.gn @@ -100,6 +100,7 @@ config("skia_public") { "SKIA_OHOS", "SKIA_OHOS_SHADER_REDUCE", "SKIA_DFX_FOR_OHOS", + "SKIA_DFX_FOR_RECORD_VKIMAGE", ] } if (is_component_build) { @@ -1616,6 +1617,9 @@ optional("gpu") { sources += skia_gpu_vk_private configs += [ ":use_skia_vulkan_headers" ] external_deps += [ "vulkan-headers:vulkan_headers" ] + if (is_ohos) { + external_deps += [ "hilog:libhilog" ] + } if (is_fuchsia) { if (using_fuchsia_sdk) { public_deps += [ "$fuchsia_sdk_root/pkg:vulkan" ] diff --git a/m133/gn/core.gni b/m133/gn/core.gni index 14294cd2eff83b6003e8c0b97d2430560cd4e893..9e285ee0823caa9d2a5740af23c1d330baa86637 100644 --- a/m133/gn/core.gni +++ b/m133/gn/core.gni @@ -70,6 +70,7 @@ skia_core_public = [ "$_include/core/SkImageFilter.h", "$_include/core/SkImageGenerator.h", "$_include/core/SkImageInfo.h", + "$_include/core/SkLog.h", "$_include/core/SkM44.h", "$_include/core/SkMallocPixelRef.h", "$_include/core/SkMaskFilter.h", diff --git a/m133/gn/gpu.gni b/m133/gn/gpu.gni index 6ead804aeaf3324c7be490f07068ff92b8aa7e23..36b697fb095087bf4fc240c1dfe23d2ac9f76b8b 100644 --- a/m133/gn/gpu.gni +++ b/m133/gn/gpu.gni @@ -747,6 +747,8 @@ skia_gpu_vk_private = [ "$_src/gpu/ganesh/vk/GrVkUtil.h", "$_src/gpu/ganesh/vk/GrVkVaryingHandler.cpp", "$_src/gpu/ganesh/vk/GrVkVaryingHandler.h", + "$_src/gpu/ganesh/vk/GrVulkanTracker.cpp", + "$_src/gpu/ganesh/vk/GrVulkanTracker.h", ] # Generated by Bazel rule //src/gpu/ganesh/vk:android_srcs diff --git a/m133/include/core/SkLog.h b/m133/include/core/SkLog.h new file mode 100644 index 0000000000000000000000000000000000000000..909c9e45d9d29af5527bf03b6d6ab8c68e1d65a5 --- /dev/null +++ b/m133/include/core/SkLog.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SKLOG_DEFINED +#define SKLOG_DEFINED + +#ifdef SKIA_OHOS +#include + +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD001406 + +#undef LOG_TAG +#define LOG_TAG "skia" + +#define SK_LOGD(fmt, ...) HILOG_DEBUG(LOG_CORE, fmt, ##__VA_ARGS__) +#define SK_LOGI(fmt, ...) HILOG_INFO(LOG_CORE, fmt, ##__VA_ARGS__) +#define SK_LOGW(fmt, ...) HILOG_WARN(LOG_CORE, fmt, ##__VA_ARGS__) +#define SK_LOGE(fmt, ...) HILOG_ERROR(LOG_CORE, fmt, ##__VA_ARGS__) +#else +#define SK_LOGD(fmt, ...) +#define SK_LOGI(fmt, ...) +#define SK_LOGW(fmt, ...) +#define SK_LOGE(fmt, ...) +#endif + +#endif // SKLOG_DEFINED diff --git a/m133/include/core/SkTypes.h b/m133/include/core/SkTypes.h index 69157da50ae922e90e0104737be0e314f6ffe826..36008e061589e6b00ac484f1446b90d41effbd90 100644 --- a/m133/include/core/SkTypes.h +++ b/m133/include/core/SkTypes.h @@ -167,6 +167,10 @@ #endif #endif +#if defined(SKIA_OHOS_SINGLE_OWNER) || defined(SKIA_DFX_FOR_RECORD_VKIMAGE) + extern bool IsRenderService(); +#endif + #ifdef SKIA_OHOS_SHADER_REDUCE extern SK_API bool SkShaderReduceProperty(); #endif diff --git a/m133/include/gpu/ganesh/GrDirectContext.h b/m133/include/gpu/ganesh/GrDirectContext.h index 15f3c71f57be13a1dbf6c2c7c722e340289e31f9..f9fb6ad64e92f9f7b7c71c016cf8c812c44dad72 100644 --- a/m133/include/gpu/ganesh/GrDirectContext.h +++ b/m133/include/gpu/ganesh/GrDirectContext.h @@ -980,6 +980,8 @@ public: void vmaDefragment(); void dumpVmaStats(SkString *out); + void dumpAllResource(std::stringstream& dump) const; + protected: GrDirectContext(GrBackendApi backend, const GrContextOptions& options, diff --git a/m133/include/gpu/vk/GrVulkanTrackerInterface.h b/m133/include/gpu/vk/GrVulkanTrackerInterface.h index 83525308e5c18b7d7540ebcf0f685f13f9347987..0fb102cab55103263280a091b834c339c7b47adf 100644 --- a/m133/include/gpu/vk/GrVulkanTrackerInterface.h +++ b/m133/include/gpu/vk/GrVulkanTrackerInterface.h @@ -18,10 +18,7 @@ #include #if defined (SK_VULKAN) && defined (SKIA_DFX_FOR_RECORD_VKIMAGE) - #define RECORD_GPU_RESOURCE_DRAWABLE_CALLER(NodeId) \ - if (ParallelDebug::IsVkImageDfxEnabled()) { \ - ParallelDebug::RecordNodeId(NodeId); \ - } + #define RECORD_GPU_RESOURCE_DRAWABLE_CALLER(NodeId) ParallelDebug::RecordNodeId(NodeId) #else #define RECORD_GPU_RESOURCE_DRAWABLE_CALLER(NodeId) #endif diff --git a/m133/src/gpu/ganesh/GrDirectContext.cpp b/m133/src/gpu/ganesh/GrDirectContext.cpp index aa0205546772fb5679b897d5a5ba8b1f54b85d94..4417504f789f05bda37429204c208c159a8d2606 100644 --- a/m133/src/gpu/ganesh/GrDirectContext.cpp +++ b/m133/src/gpu/ganesh/GrDirectContext.cpp @@ -593,6 +593,14 @@ bool GrDirectContext::supportsDistanceFieldText() const { ////////////////////////////////////////////////////////////////////////////// +void GrDirectContext::dumpAllResource(std::stringstream &dump) const { +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + if (fResourceCache) { + fResourceCache->dumpAllResource(dump); + } +#endif +} + void GrDirectContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { ASSERT_SINGLE_OWNER fResourceCache->dumpMemoryStatistics(traceMemoryDump); diff --git a/m133/src/gpu/ganesh/GrGpuResource.h b/m133/src/gpu/ganesh/GrGpuResource.h index 175c8b46566fe0c156f5effca86ef9f7a0a17adb..b8c287e858194f8f19f4eb8030b4fa504ed846f4 100644 --- a/m133/src/gpu/ganesh/GrGpuResource.h +++ b/m133/src/gpu/ganesh/GrGpuResource.h @@ -19,6 +19,9 @@ #include #include #include +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include +#endif #include #include @@ -339,6 +342,12 @@ public: */ GrGpuResourceTag getResourceTag() const { return fGrResourceTag; } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + virtual void dumpVkImageInfo(std::stringstream& dump) const { + dump << "\n"; + } +#endif + #if defined(GPU_TEST_UTILS) virtual const GrSurface* asSurface() const { return nullptr; } #endif diff --git a/m133/src/gpu/ganesh/GrResourceCache.cpp b/m133/src/gpu/ganesh/GrResourceCache.cpp index 2002fa46da230ff3e9d1831255a5616c3d924d72..0ead5dc7a241cc83c84dbf736e441abc4411deb1 100644 --- a/m133/src/gpu/ganesh/GrResourceCache.cpp +++ b/m133/src/gpu/ganesh/GrResourceCache.cpp @@ -1275,6 +1275,40 @@ uint32_t GrResourceCache::getNextTimestamp() { return fTimestamp++; } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +void GrResourceCache::dumpAllResource(std::stringstream &dump) const { + if (getResourceCount() == 0) { + return; + } + dump << "Purgeable: " << fPurgeableQueue.count() << std::endl; + for (int i = 0; i < fPurgeableQueue.count(); ++i) { + GrGpuResource* resource = fPurgeableQueue.at(i); + if (resource == nullptr) { + continue; + } + if (strcmp(resource->getResourceType(), "VkImage") != 0) { + continue; + } + resource->dumpVkImageInfo(dump); + } + dump << "Non-Purgeable: " << fNonpurgeableResources.size() << std::endl; + for (int i = 0; i < fNonpurgeableResources.size(); ++i) { + GrGpuResource* resource = fNonpurgeableResources[i]; + if (resource == nullptr) { + continue; + } + if (strcmp(resource->getResourceType(), "VkImage") != 0) { + continue; + } + resource->dumpVkImageInfo(dump); + } +#ifdef SK_VULKAN + dump << "Destroy Record: " << std::endl; + ParallelDebug::DumpAllDestroyVkImage(dump); +#endif +} +#endif + void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { for (int i = 0; i < fNonpurgeableResources.size(); ++i) { fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump); diff --git a/m133/src/gpu/ganesh/GrResourceCache.h b/m133/src/gpu/ganesh/GrResourceCache.h index ce9f6d23452989940489d2fabe7955caee6b9064..60384774f1c4a9d26e267ba04be319c35225bad3 100644 --- a/m133/src/gpu/ganesh/GrResourceCache.h +++ b/m133/src/gpu/ganesh/GrResourceCache.h @@ -134,6 +134,11 @@ public: * Returns the number of bytes consumed by resources. */ size_t getResourceBytes() const { return fBytes; } + +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + void dumpAllResource(std::stringstream& dump) const; +#endif + #ifdef SKIA_DFX_FOR_OHOS void addAllocImageBytes(size_t bytes) { fAllocImageBytes += bytes; } void removeAllocImageBytes(size_t bytes) { fAllocImageBytes -= bytes; } diff --git a/m133/src/gpu/ganesh/GrSurface.h b/m133/src/gpu/ganesh/GrSurface.h index 97f9fbc59d3fcd9e39860ddc623717eed7ecea6c..1b704779b923850d17be253e67ba05dbe8367b7e 100644 --- a/m133/src/gpu/ganesh/GrSurface.h +++ b/m133/src/gpu/ganesh/GrSurface.h @@ -115,6 +115,10 @@ public: const GrSurface* asSurface() const override { return this; } #endif +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + virtual void updateNodeId(uint64_t nodeId) {} +#endif + protected: void setGLRTFBOIDIs0() { SkASSERT(!this->requiresManualMSAAResolve()); diff --git a/m133/src/gpu/ganesh/GrSurfaceProxy.cpp b/m133/src/gpu/ganesh/GrSurfaceProxy.cpp index 4f0f58d848a6ee03c3a41311adf0a5a005d80e98..a98ab0df41a7a169d738f25195e1fa179fe8a501 100644 --- a/m133/src/gpu/ganesh/GrSurfaceProxy.cpp +++ b/m133/src/gpu/ganesh/GrSurfaceProxy.cpp @@ -12,6 +12,9 @@ #include "include/core/SkPoint.h" #include "include/gpu/GpuTypes.h" #include "include/gpu/ganesh/GrRecordingContext.h" +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include "include/gpu/vk/GrVulkanTrackerInterface.h" +#endif #include "src/gpu/SkBackingFit.h" #include "src/gpu/Swizzle.h" #include "src/gpu/ganesh/GrCaps.h" @@ -52,6 +55,17 @@ static bool is_valid_non_lazy(SkISize dimensions) { } #endif +// emulator mock +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#ifndef SK_VULKAN +namespace ParallelDebug { +bool IsVkImageDfxEnabled() { return false; } +void RecordNodeId(uint64_t nodeId) {} +uint64_t GetNodeId() { return 0; } +} +#endif +#endif + GrSurfaceProxy::LazyCallbackResult::LazyCallbackResult(sk_sp surf, bool releaseCallback, LazyInstantiationKeyMode mode) @@ -74,6 +88,9 @@ GrSurfaceProxy::GrSurfaceProxy(const GrBackendFormat& format, , fFit(fit) , fBudgeted(budgeted) , fUseAllocator(useAllocator) +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + , fNodeId(ParallelDebug::GetNodeId()) +#endif , fIsProtected(isProtected) , fLabel(label) { SkASSERT(fFormat.isValid()); @@ -97,6 +114,9 @@ GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, , fBudgeted(budgeted) , fUseAllocator(useAllocator) , fLazyInstantiateCallback(std::move(callback)) +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + , fNodeId(ParallelDebug::GetNodeId()) +#endif , fIsProtected(isProtected) , fLabel(label) { SkASSERT(fFormat.isValid()); @@ -118,6 +138,9 @@ GrSurfaceProxy::GrSurfaceProxy(sk_sp surface, : skgpu::Budgeted::kNo) , fUseAllocator(useAllocator) , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID! +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + , fNodeId(ParallelDebug::GetNodeId()) +#endif , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo) , fLabel(fTarget->getLabel()) { SkASSERT(fFormat.isValid()); @@ -126,10 +149,27 @@ GrSurfaceProxy::GrSurfaceProxy(sk_sp surface, GrSurfaceProxy::~GrSurfaceProxy() { } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +struct NodeIdHelper { + explicit inline NodeIdHelper(uint64_t nodeId): initNodeId_(ParallelDebug::GetNodeId()) + { + ParallelDebug::RecordNodeId(nodeId); + } + inline ~NodeIdHelper() + { + ParallelDebug::RecordNodeId(initNodeId_); + } + uint64_t initNodeId_; +}; +#endif + sk_sp GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider, int sampleCnt, GrRenderable renderable, skgpu::Mipmapped mipmapped) const { +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + NodeIdHelper helper(fNodeId); +#endif SkASSERT(mipmapped == skgpu::Mipmapped::kNo || fFit == SkBackingFit::kExact); SkASSERT(!this->isLazy()); SkASSERT(!fTarget); @@ -159,6 +199,11 @@ sk_sp GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceP if (!surface) { return nullptr; } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + if (ParallelDebug::IsVkImageDfxEnabled()) { + surface->updateNodeId(fNodeId); + } +#endif if (fGrProxyTag.isGrTagValid()) { surface->setResourceTag(fGrProxyTag); @@ -449,6 +494,9 @@ bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvide bool syncKey = true; bool releaseCallback = false; if (!surface) { +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + NodeIdHelper helper(fNodeId); +#endif auto result = fProxy->fLazyInstantiateCallback(resourceProvider, fProxy->callbackDesc()); surface = std::move(result.fSurface); syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced; @@ -458,6 +506,11 @@ bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvide fProxy->fDimensions.setEmpty(); return false; } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + if (ParallelDebug::IsVkImageDfxEnabled()) { + surface->updateNodeId(fNodeId); + } +#endif if (fProxy->isFullyLazy()) { // This was a fully lazy proxy. We need to fill in the width & height. For partially diff --git a/m133/src/gpu/ganesh/GrSurfaceProxy.h b/m133/src/gpu/ganesh/GrSurfaceProxy.h index 5b2689c7e5c94235d4d3a32683e29488e9aec959..f0a7e7445cf8f3a59c6a427e5346b48f328a1d6e 100644 --- a/m133/src/gpu/ganesh/GrSurfaceProxy.h +++ b/m133/src/gpu/ganesh/GrSurfaceProxy.h @@ -493,6 +493,10 @@ private: bool fIgnoredByResourceAllocator = false; bool fIsDDLTarget = false; bool fIsPromiseProxy = false; +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + uint64_t fNodeId; +#endif + GrProtected fIsProtected; int fTaskTargetCount = 0; diff --git a/m133/src/gpu/ganesh/GrSurfaceProxyPriv.h b/m133/src/gpu/ganesh/GrSurfaceProxyPriv.h index 94acffd6166f8e6c04662dc5388bb4d176ac0e76..cbe2593c647871ac0e39ac51e91adfceb7f679b4 100644 --- a/m133/src/gpu/ganesh/GrSurfaceProxyPriv.h +++ b/m133/src/gpu/ganesh/GrSurfaceProxyPriv.h @@ -13,6 +13,9 @@ #include "src/gpu/SkBackingFit.h" #include "src/gpu/ganesh/GrSurface.h" #include "src/gpu/ganesh/GrSurfaceProxy.h" +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include "include/gpu/vk/GrVulkanTrackerInterface.h" +#endif #include @@ -55,7 +58,11 @@ public: void setIsPromiseProxy() { fProxy->fIsPromiseProxy = true; } private: +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + explicit GrSurfaceProxyPriv(GrSurfaceProxy* proxy) : fProxy(proxy), fNodeId(ParallelDebug::GetNodeId()) {} +#else explicit GrSurfaceProxyPriv(GrSurfaceProxy* proxy) : fProxy(proxy) {} +#endif GrSurfaceProxyPriv& operator=(const GrSurfaceProxyPriv&) = delete; // No taking addresses of this type. @@ -63,6 +70,9 @@ private: GrSurfaceProxyPriv* operator&(); GrSurfaceProxy* fProxy; +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + uint64_t fNodeId; +#endif friend class GrSurfaceProxy; // to construct/copy this type. }; diff --git a/m133/src/gpu/ganesh/vk/GrVkGpu.cpp b/m133/src/gpu/ganesh/vk/GrVkGpu.cpp index 39b88893042e7e7caef5568b0f52bf1a016d7594..d1fe8bdc8fb27c57e9ab26a2ee46eb234927c4e0 100644 --- a/m133/src/gpu/ganesh/vk/GrVkGpu.cpp +++ b/m133/src/gpu/ganesh/vk/GrVkGpu.cpp @@ -8,6 +8,9 @@ #include "src/gpu/ganesh/vk/GrVkGpu.h" #include "include/core/SkImageInfo.h" +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include "include/core/SkLog.h" +#endif #include "include/core/SkPoint.h" #include "include/core/SkRect.h" #include "include/core/SkSamplingOptions.h" @@ -2783,6 +2786,72 @@ void GrVkGpu::endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin, this->didWriteToSurface(target, origin, &bounds); } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +void GrVkGpu::dumpDeviceFaultInfo(const std::string& errorCategory) { + VkDeviceFaultCountsEXT fc{}; + fc.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT; + fc.pNext = nullptr; + GR_VK_CALL(this->vkInterface(), GetDeviceFaultInfo(fDevice, &fc, nullptr)); + + const uint32_t vendorBinarySize = + std::min(uint32_t(fc.vendorBinarySize), std::numeric_limits::max()); + std::vector addressInfos (fc.addressInfoCount); + std::vector vendorInfos (fc.vendorInfoCount); + std::vector vendorBinaryData(vendorBinarySize); + VkDeviceFaultInfoEXT fi{}; + VkDebugUtilsObjectNameInfoEXT nameInfo{}; + fi.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT; + fi.pNext = &nameInfo; + fi.pAddressInfos = addressInfos.data(); + fi.pVendorInfos = vendorInfos.data(); + fi.pVendorBinaryData = vendorBinaryData.data(); + GR_VK_CALL(this->vkInterface(), GetDeviceFaultInfo(fDevice, &fc, &fi)); + if (!fi.pNext) { + SK_LOGE("GrVkGpu::dumpDeviceFaultInfo %{public}s pNext is nullptr", errorCategory.c_str()); + return; + } + auto obj = static_cast(fi.pNext); + if (obj == nullptr) { + SK_LOGE("GrVkGpu::dumpDeviceFaultInfo %{public}s obj is nullptr", errorCategory.c_str()); + return; + } + auto vkImage = obj->objectHandle; + if (!vkImage) { + SK_LOGE("GrVkGpu::dumpDeviceFaultInfo %{public}s vkimage is nullptr", errorCategory.c_str()); + return; + } + SK_LOGE("GrVkGpu::dumpDeviceFaultInfo %{public}s vkimage 0x%{public}llx", errorCategory.c_str(), vkImage); +} + +void GrVkGpu::dumpVkImageDfx(const std::string& errorCategory) { + if (!ParallelDebug::IsVkImageDfxEnabled()) { + return; + } + dumpDeviceFaultInfo(errorCategory); + auto context = getContext(); + if (context == nullptr) { + SK_LOGE("GrVkGpu::dumpVkImageDfx %{public}s context nullptr", errorCategory.c_str()); + return; + } + std::stringstream dump; + context->dumpAllResource(dump); + std::string s; + while (std::getline(dump, s, '\n')) { + SK_LOGE("%{public}s", s.c_str()); + } +} +#endif + +void GrVkGpu::reportVulkanError(const std::string& errorCategory) { + auto context = getContext(); + if (context == nullptr) { + SK_LOGE("GrVkGpu::reportVulkanError %{public}s context nullptr", errorCategory.c_str()); + return; + } + SK_LOGE("GrVkGpu::reportVulkanError report %{public}s", errorCategory.c_str()); + context->processVulkanError(); +} + bool GrVkGpu::checkVkResult(VkResult result) { int32_t numResult = static_cast(result); switch (numResult) { @@ -2798,12 +2867,10 @@ bool GrVkGpu::checkVkResult(VkResult result) { fDeviceLostProc, vkCaps().supportsDeviceFaultInfo()); } - { - auto context = getContext(); - if (context) { - context->processVulkanError(); - } - } + reportVulkanError("VK_ERROR_DEVICE_LOST"); +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + dumpVkImageDfx("VK_ERROR_DEVICE_LOST"); +#endif abort(); return false; case VK_ERROR_OUT_OF_DEVICE_MEMORY: @@ -2811,13 +2878,11 @@ bool GrVkGpu::checkVkResult(VkResult result) { this->setOOMed(); return false; case VK_HUAWEI_GPU_ERROR_RECOVER: - { - auto context = getContext(); - if (context) { - context->processVulkanError(); - } - return true; - } + reportVulkanError("VK_HUAWEI_GPU_ERROR_RECOVER"); +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + dumpVkImageDfx("VK_HUAWEI_GPU_ERROR_RECOVER"); +#endif + return true; default: return false; } diff --git a/m133/src/gpu/ganesh/vk/GrVkGpu.h b/m133/src/gpu/ganesh/vk/GrVkGpu.h index ec4d069093dc9feec780ebdbf530d7a775ff4483..40d3ad24b9b3961f807d1dba35c890b6718583dd 100644 --- a/m133/src/gpu/ganesh/vk/GrVkGpu.h +++ b/m133/src/gpu/ganesh/vk/GrVkGpu.h @@ -466,6 +466,13 @@ private: GrVkImageInfo*, GrProtected); + // checkVkResult dfx +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + void dumpDeviceFaultInfo(const std::string& errorCategory); + void dumpVkImageDfx(const std::string& errorCategory); +#endif + void reportVulkanError(const std::string& errorCategory); + sk_sp fInterface; sk_sp fMemoryAllocator; sk_sp fMemoryAllocatorCacheImage; diff --git a/m133/src/gpu/ganesh/vk/GrVkImage.cpp b/m133/src/gpu/ganesh/vk/GrVkImage.cpp index 0baff47d77ebf12f840ad3501769d47587677e05..35bf14d6085a119f9b031968112bcb761f08d325 100644 --- a/m133/src/gpu/ganesh/vk/GrVkImage.cpp +++ b/m133/src/gpu/ganesh/vk/GrVkImage.cpp @@ -7,6 +7,9 @@ #include "src/gpu/ganesh/vk/GrVkImage.h" +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include "include/core/SkLog.h" +#endif #include "include/core/SkSize.h" #include "include/gpu/vk/VulkanMutableTextureState.h" #include "src/gpu/ganesh/vk/GrVkCaps.h" @@ -16,6 +19,9 @@ #include "src/gpu/ganesh/vk/GrVkResourceProvider.h" #include "src/gpu/ganesh/vk/GrVkUniformHandler.h" #include "src/gpu/ganesh/vk/GrVkUtil.h" +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include "src/gpu/ganesh/vk/GrVulkanTracker.h" +#endif #include "src/gpu/vk/VulkanMemory.h" #include "src/gpu/vk/VulkanMutableTextureStatePriv.h" #include "src/gpu/vk/VulkanUtilsPriv.h" @@ -654,7 +660,62 @@ void GrVkImage::setResourceRelease(sk_sp releaseHelper) { fResource->setRelease(std::move(releaseHelper)); } +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +void GrVkImage::dumpVkImageInfo(std::stringstream& dump) const { + auto vkGpu = getVkGpu(); + if (vkGpu == nullptr) { + SK_LOGE("GrVkImage::dumpVkImageInfo vkGpu nullptr"); + return; + } + VkMemoryRequirements memRequirements; + VK_CALL(vkGpu, GetImageMemoryRequirements(vkGpu->device(), image(), &memRequirements)); + VkDeviceSize imageSize = memRequirements.size; + + if (fResource == nullptr) { + SK_LOGE("GrVkImage::dumpVkImageInfo fResource nullptr"); + return; + } + fResource->dumpVkImageResource(dump); + dump << "Borrowed: " << isBorrowed() << ", " << "ImageSize: " << imageSize << ", "; + if (fResource->fCaller == nullptr) { + SK_LOGE("GrVkImage::dumpVkImageInfo fCaller nullptr"); + } else { + fResource->fCaller->Dump(dump); + } + dump << "\n"; +} + +void GrVkImage::Resource::dumpVkImageResource(std::stringstream& dump) { + dump << "VkImage: " << fImage << ", " + << "Memory: " << fAlloc.fMemory << ", " + << "Offset: " << fAlloc.fOffset << ", " + << "Size: " << fAlloc.fSize << ", "; +} + +void GrVkImage::Resource::RecordFreeVkImage(bool isBorrowed) const { + static const bool isInRenderSevice = IsRenderService(); + if (isInRenderSevice) { + ParallelDebug::VkImageDestroyRecord::Record(fImage, isBorrowed, fCaller, fAlloc.fMemory); + } +} + +void GrVkImage::updateNodeId(uint64_t nodeId) { + if (fResource && fResource->fCaller) { + fResource->fCaller->nodeId_ = nodeId; + } +} +#endif + +GrVkImage::Resource::~Resource() { +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + ParallelDebug::DestroyVkImageInvokeRecord(fCaller); +#endif +} + void GrVkImage::Resource::freeGPUData() const { +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + RecordFreeVkImage(true); +#endif this->invokeReleaseProc(); VK_CALL(fGpu, DestroyImage(fGpu->device(), fImage, nullptr)); #ifdef SKIA_DFX_FOR_OHOS @@ -664,6 +725,9 @@ void GrVkImage::Resource::freeGPUData() const { } void GrVkImage::BorrowedResource::freeGPUData() const { +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + RecordFreeVkImage(true); +#endif this->invokeReleaseProc(); } diff --git a/m133/src/gpu/ganesh/vk/GrVkImage.h b/m133/src/gpu/ganesh/vk/GrVkImage.h index dbe36f15b02a77da0a1b3c69f33970c2932c32d3..59c153e0f66137e3d470ee9078e007bed9bd60ce 100644 --- a/m133/src/gpu/ganesh/vk/GrVkImage.h +++ b/m133/src/gpu/ganesh/vk/GrVkImage.h @@ -16,6 +16,9 @@ #include "include/gpu/ganesh/GrTypes.h" #include "include/gpu/ganesh/vk/GrVkBackendSurface.h" #include "include/gpu/ganesh/vk/GrVkTypes.h" +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +#include "include/gpu/vk/GrVulkanTrackerInterface.h" +#endif #include "include/gpu/vk/VulkanMutableTextureState.h" #include "include/gpu/vk/VulkanTypes.h" #include "include/private/base/SkDebug.h" @@ -222,6 +225,12 @@ public: static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout); size_t onGpuMemorySize() const override; + +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + void dumpVkImageInfo(std::stringstream& dump) const override; + void updateNodeId(uint64_t nodeId) override; +#endif + #if defined(GPU_TEST_UTILS) void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu); #endif @@ -309,7 +318,7 @@ private: , fImage(image) , fAlloc(alloc) {} - ~Resource() override {} + ~Resource() override; #ifdef SK_TRACE_MANAGED_RESOURCES void dumpInfo() const override { @@ -317,6 +326,12 @@ private: } #endif +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + ParallelDebug::VkImageInvokeRecord* fCaller = ParallelDebug::GenerateVkImageInvokeRecord(); + void dumpVkImageResource(std::stringstream& dump); + void RecordFreeVkImage(bool isBorrowed) const; +#endif + #ifdef SK_DEBUG const GrManagedResource* asVkImageResource() const override { return this; } #endif diff --git a/m133/src/gpu/ganesh/vk/GrVkTexture.cpp b/m133/src/gpu/ganesh/vk/GrVkTexture.cpp index a71e37a8ca13a65e9a9051709d47e5fd9598646c..36731ac660e0860e9302c169bb3e9d2ab0ddbb1a 100644 --- a/m133/src/gpu/ganesh/vk/GrVkTexture.cpp +++ b/m133/src/gpu/ganesh/vk/GrVkTexture.cpp @@ -239,3 +239,11 @@ void GrVkTexture::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const resourceName.append("/texture"); this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "Texture", size); } + +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE +void GrVkTexture::updateNodeId(uint64_t nodeId) { + if (fTexture != nullptr) { + fTexture->updateNodeId(nodeId); + } +} +#endif diff --git a/m133/src/gpu/ganesh/vk/GrVkTexture.h b/m133/src/gpu/ganesh/vk/GrVkTexture.h index 64679f493ec13d23003c33b292e3d8080fc832e4..83a0a3ef0e792c6dc7b4eda5b6f4c0fa6ad3a707 100644 --- a/m133/src/gpu/ganesh/vk/GrVkTexture.h +++ b/m133/src/gpu/ganesh/vk/GrVkTexture.h @@ -76,6 +76,10 @@ public: void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override; +#ifdef SKIA_DFX_FOR_RECORD_VKIMAGE + void updateNodeId(uint64_t nodeId) override; +#endif + protected: GrVkTexture(GrVkGpu*, SkISize dimensions, diff --git a/m133/src/gpu/ganesh/vk/GrVulkanTracker.cpp b/m133/src/gpu/ganesh/vk/GrVulkanTracker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ea4a6d1ff50029215797b7c3e2641b3fe48cb3e --- /dev/null +++ b/m133/src/gpu/ganesh/vk/GrVulkanTracker.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "src/gpu/ganesh/vk/GrVulkanTracker.h" + +#include "include/gpu/vk/GrVulkanTrackerInterface.h" + +#include +#include + +static thread_local ParallelDebug::VkImageInvokeRecord g_caller; +static thread_local std::deque g_delete; +static constexpr size_t DESTROY_RECORD_CAPACITY = 100; + +static inline int64_t GetNanoSecords() +{ + struct timespec ts {}; + clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 100000000LL + ts.tv_nsec; +} + +bool ParallelDebug::IsVkImageDfxEnabled() +{ + static const bool dfxEnabled = + std::atoi(OHOS::system::GetParameter("persist.sys.graphic.openVkImageMemoryDfx", "0").c_str()) != 0; + return dfxEnabled; +} + +uint64_t ParallelDebug::GetNodeId() +{ + return g_caller.nodeId_; +} + +void ParallelDebug::RecordNodeId(uint64_t nodeId) +{ + g_caller.nodeId_ = nodeId; +} + +ParallelDebug::VkImageInvokeRecord* ParallelDebug::GenerateVkImageInvokeRecord() +{ + auto caller = new ParallelDebug::VkImageInvokeRecord(); + caller->nodeId_ = g_caller.nodeId_; + return caller; +} + +void ParallelDebug::DestroyVkImageInvokeRecord(ParallelDebug::VkImageInvokeRecord* vkImageInvokeRecord) +{ + delete vkImageInvokeRecord; +} + +void ParallelDebug::VkImageInvokeRecord::Dump(std::stringstream& ss) +{ + ss << (nodeId_ ? ", nodeId: " + std::to_string(nodeId_) : ""); +} + +void ParallelDebug::VkImageDestroyRecord::Record(VkImage image, + bool borrow, + const ParallelDebug::VkImageInvokeRecord* call, + VkDeviceMemory memory) +{ + if (call == nullptr) { + return; + } + g_delete.push_back({image, borrow, *call, memory, GetNanoSecords()}); + if (g_delete.size() > DESTROY_RECORD_CAPACITY) { + g_delete.pop_front(); + } +} + +void ParallelDebug::DumpAllDestroyVkImage(std::stringstream &ss) +{ + for (auto& del : g_delete) { + del.Dump(ss); + ss << "\n"; + } +} + +void ParallelDebug::VkImageDestroyRecord::Dump(std::stringstream& ss) +{ + char timeStr[20]; + struct tm timeInfo; + time_t seconds = timeStamp_ / 1000000000LL; + localtime_r(&seconds, &timeInfo); + std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeInfo); + ss << timeStr << "VkImage: " << image_ << ", " << borrowed_ << ", " << memory_ << " "; + caller_.Dump(ss); +} diff --git a/m133/src/gpu/ganesh/vk/GrVulkanTracker.h b/m133/src/gpu/ganesh/vk/GrVulkanTracker.h new file mode 100644 index 0000000000000000000000000000000000000000..c1f4b9213f6d2ff47bb431a44b8415ef196b1e84 --- /dev/null +++ b/m133/src/gpu/ganesh/vk/GrVulkanTracker.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GrVulkanTracker_DEFINED +#define GrVulkanTracker_DEFINED + +#include "src/gpu/ganesh/vk/GrVkImage.h" + +#include +#include + +namespace ParallelDebug { +struct VkImageInvokeRecord { + void Dump(std::stringstream& ss); + + uint64_t nodeId_; +}; + +struct VkImageDestroyRecord { + static void Record(VkImage image, bool borrow, const VkImageInvokeRecord* call, VkDeviceMemory memory); + void Dump(std::stringstream& ss); + + VkImage image_; + bool borrowed_; + VkImageInvokeRecord caller_; + VkDeviceMemory memory_; + int64_t timeStamp_; +}; +} +#endif diff --git a/m133/src/ports/SkDebug_ohos.cpp b/m133/src/ports/SkDebug_ohos.cpp index f74bc0b98f3035360c46e6060c884c88fd243a56..ee59e51fc2a66519b8008c58ff65a14464033ff5 100644 --- a/m133/src/ports/SkDebug_ohos.cpp +++ b/m133/src/ports/SkDebug_ohos.cpp @@ -18,12 +18,15 @@ #define LOG_TAG "skia" #include "hilog/log.h" +#if defined(SKIA_OHOS_SINGLE_OWNER) || defined(SKIA_DFX_FOR_RECORD_VKIMAGE) +#include "include/core/SkLog.h" +#include +#endif + #ifdef SKIA_OHOS_SINGLE_OWNER #include "backtrace_local.h" -#include "include/core/SkLog.h" #include #include -#include #endif extern "C" { @@ -57,8 +60,8 @@ bool SkShaderReduceProperty() } #endif -#ifdef SKIA_OHOS_SINGLE_OWNER -static bool IsRenderService() +#if defined(SKIA_OHOS_SINGLE_OWNER) || defined(SKIA_DFX_FOR_RECORD_VKIMAGE) +bool IsRenderService() { std::ifstream procfile("/proc/self/cmdline"); if (!procfile.is_open()) { @@ -72,7 +75,9 @@ static bool IsRenderService() bool result = processName.compare(0, target.size(), target) == 0; return result; } +#endif +#ifdef SKIA_OHOS_SINGLE_OWNER static bool IsBeta() { static const bool isBeta = OHOS::system::GetParameter("const.logsystem.versiontype", "unknown") == "beta";