diff --git a/renderdoc/api/replay/d3d11_pipestate.h b/renderdoc/api/replay/d3d11_pipestate.h index 28a9afb4a..6ed2ef875 100644 --- a/renderdoc/api/replay/d3d11_pipestate.h +++ b/renderdoc/api/replay/d3d11_pipestate.h @@ -302,7 +302,7 @@ struct D3D11PipelineState struct RTBlend { - RTBlend() : Enabled(false), WriteMask(0) {} + RTBlend() : Enabled(false), LogicEnabled(false), WriteMask(0) {} struct BlendOp { rdctype::str Source; diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index b4ccd2520..9b25ec12d 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -284,6 +284,17 @@ struct FetchFrameStatistics struct FetchFrameInfo { + FetchFrameInfo() + : frameNumber(0), + firstEvent(0), + fileOffset(0), + fileSize(0), + persistentSize(0), + initDataSize(0), + captureTime(0) + { + } + uint32_t frameNumber; uint32_t firstEvent; uint64_t fileOffset; diff --git a/renderdoc/api/replay/gl_pipestate.h b/renderdoc/api/replay/gl_pipestate.h index f4854d1ab..5a7377c23 100644 --- a/renderdoc/api/replay/gl_pipestate.h +++ b/renderdoc/api/replay/gl_pipestate.h @@ -206,6 +206,12 @@ struct GLPipelineState struct Feedback { + Feedback() : Active(false), Paused(false) + { + Offset[0] = Offset[1] = Offset[2] = Offset[3] = 0; + Size[0] = Size[1] = Size[2] = Size[3] = 0; + } + ResourceId Obj; ResourceId BufferBinding[4]; uint64_t Offset[4]; diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 95c5dd5be..d2f1b1b39 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1036,6 +1036,7 @@ void Serialiser::Serialise(const char *name, FetchTexture &el) Serialise("", el.creationFlags); Serialise("", el.msQual); Serialise("", el.msSamp); + Serialise("", el.byteSize); SIZE_CHECK(FetchTexture, 152); } diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 62d497765..6a2f4e708 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -164,11 +164,9 @@ D3D11DebugManager::~D3D11DebugManager() SaveShaderCache("d3dshaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion, m_ShaderCache, ShaderCacheCallbacks); } - else - { - for(auto it = m_ShaderCache.begin(); it != m_ShaderCache.end(); ++it) - ShaderCacheCallbacks.Destroy(it->second); - } + + for(auto it = m_ShaderCache.begin(); it != m_ShaderCache.end(); ++it) + ShaderCacheCallbacks.Destroy(it->second); ShutdownFontRendering(); ShutdownStreamOut(); diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index cf886e853..ce7fde3f1 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -3016,7 +3016,9 @@ void Serialiser::Serialise(const char *name, VkPhysicalDeviceProperties &el) Serialise("deviceID", el.deviceID); Serialise("deviceType", el.deviceType); - string deviceName = el.deviceName; + string deviceName; + if(m_Mode == WRITING) + deviceName = el.deviceName; Serialise("deviceName", deviceName); if(m_Mode == READING) { @@ -3101,8 +3103,8 @@ void Serialiser::Deserialise(const VkDeviceCreateInfo *const el) const for(uint32_t i = 0; i < el->queueCreateInfoCount; i++) delete[] el->pQueueCreateInfos[i].pQueuePriorities; delete[] el->pQueueCreateInfos; - delete el->ppEnabledExtensionNames; - delete el->ppEnabledLayerNames; + delete[] el->ppEnabledExtensionNames; + delete[] el->ppEnabledLayerNames; delete el->pEnabledFeatures; } } @@ -4141,8 +4143,8 @@ void Serialiser::Deserialise(const VkGraphicsPipelineCreateInfo *const el) const if(el->pVertexInputState) { RDCASSERT(el->pVertexInputState->pNext == NULL); // otherwise delete - delete el->pVertexInputState->pVertexBindingDescriptions; - delete el->pVertexInputState->pVertexAttributeDescriptions; + delete[] el->pVertexInputState->pVertexBindingDescriptions; + delete[] el->pVertexInputState->pVertexAttributeDescriptions; delete el->pVertexInputState; } if(el->pInputAssemblyState) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 14d0317fa..668734222 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -328,6 +328,8 @@ private: struct BakedCmdBufferInfo { + BakedCmdBufferInfo() : draw(NULL) {} + ~BakedCmdBufferInfo() { SAFE_DELETE(draw); } vector curEvents; vector debugMessages; list drawStack; @@ -446,6 +448,12 @@ private: // need it on replay too struct DescriptorSetInfo { + ~DescriptorSetInfo() + { + for(size_t i = 0; i < currentBindings.size(); i++) + delete[] currentBindings[i]; + currentBindings.clear(); + } ResourceId layout; vector currentBindings; }; diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index a7d9debf9..a7e62720b 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -1461,8 +1461,6 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev) RDCASSERTEQUAL(vkr, VK_SUCCESS); } - m_CacheShaders = false; - attState.blendEnable = false; pipeInfo.layout = m_CheckerboardPipeLayout; @@ -1655,6 +1653,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev) } } + m_CacheShaders = false; + { compPipeInfo.stage.module = module[MESHCS]; compPipeInfo.layout = m_MeshPickLayout; @@ -2101,11 +2101,9 @@ VulkanDebugManager::~VulkanDebugManager() SaveShaderCache("vkshaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion, m_ShaderCache, ShaderCacheCallbacks); } - else - { - for(auto it = m_ShaderCache.begin(); it != m_ShaderCache.end(); ++it) - ShaderCacheCallbacks.Destroy(it->second); - } + + for(auto it = m_ShaderCache.begin(); it != m_ShaderCache.end(); ++it) + ShaderCacheCallbacks.Destroy(it->second); for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) { diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index e3bdd14c3..f8f71ea90 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -108,7 +108,7 @@ public: vector GetDebugMessages(); void SavePipelineState(); - D3D11PipelineState GetD3D11PipelineState() { return m_D3D11PipelineState; } + D3D11PipelineState GetD3D11PipelineState() { return D3D11PipelineState(); } GLPipelineState GetGLPipelineState() { return GLPipelineState(); } VulkanPipelineState GetVulkanPipelineState() { return m_VulkanPipelineState; } void FreeTargetResource(ResourceId id); @@ -260,7 +260,6 @@ private: }; VulkanPipelineState m_VulkanPipelineState; - D3D11PipelineState m_D3D11PipelineState; map m_OutputWindows; uint64_t m_OutputWinID; diff --git a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp index 377f0ede3..06506bca6 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp @@ -281,6 +281,11 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(Serialiser *localSerialiser, range.layerCount = info.imageArrayLayers; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + m_ImageLayouts[liveId].extent = iminfo.extent; + m_ImageLayouts[liveId].format = iminfo.format; + m_ImageLayouts[liveId].layerCount = 1; + m_ImageLayouts[liveId].levelCount = 1; + m_ImageLayouts[liveId].subresourceStates.clear(); m_ImageLayouts[liveId].subresourceStates.push_back( ImageRegionState(range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED)); diff --git a/renderdoc/os/posix/posix_threading.cpp b/renderdoc/os/posix/posix_threading.cpp index cfa1dd696..08a7ab1d8 100644 --- a/renderdoc/os/posix/posix_threading.cpp +++ b/renderdoc/os/posix/posix_threading.cpp @@ -125,21 +125,29 @@ struct TLSData vector data; }; +static CriticalSection *m_TLSListLock = NULL; +static vector *m_TLSList = NULL; + void Init() { int err = pthread_key_create(&OSTLSHandle, NULL); if(err != 0) RDCFATAL("Can't allocate OS TLS slot"); + m_TLSListLock = new CriticalSection(); + m_TLSList = new vector(); + CacheDebuggerPresent(); } void Shutdown() { - // let the TLS data leak. It's not great, but it's only a few kb per thread - // that we actually use (ie. not short-lived threads that don't use our TLS). - // We don't have a realistic alternative as the threads aren't ours when in-app - // and there may not be a way to have something call on thread death. + for(size_t i = 0; i < m_TLSList->size(); i++) + delete m_TLSList->at(i); + + delete m_TLSList; + delete m_TLSListLock; + pthread_key_delete(OSTLSHandle); } @@ -173,6 +181,13 @@ void SetTLSValue(uint64_t slot, void *value) { slots = new TLSData; pthread_setspecific(OSTLSHandle, slots); + + // in the case where this thread is entirely new, we globally lock so we can + // store its data for shutdown (as we might not get notified of every thread + // that exits). This only happens once, so we take the hit of the lock. + m_TLSListLock->Lock(); + m_TLSList->push_back(slots); + m_TLSListLock->Unlock(); } if(slot - 1 >= slots->data.size()) diff --git a/renderdoc/os/win32/win32_threading.cpp b/renderdoc/os/win32/win32_threading.cpp index 462baf40b..5c86723ae 100644 --- a/renderdoc/os/win32/win32_threading.cpp +++ b/renderdoc/os/win32/win32_threading.cpp @@ -130,19 +130,27 @@ struct TLSData vector data; }; +static CriticalSection *m_TLSListLock = NULL; +static vector *m_TLSList = NULL; + void Init() { OSTLSHandle = TlsAlloc(); if(OSTLSHandle == TLS_OUT_OF_INDEXES) RDCFATAL("Can't allocate OS TLS slot"); + + m_TLSListLock = new CriticalSection(); + m_TLSList = new vector(); } void Shutdown() { - // let the TLS data leak. It's not great, but it's only a few kb per thread - // that we actually use (ie. not short-lived threads that don't use our TLS). - // We don't have a realistic alternative as the threads aren't ours when in-app - // and there may not be a way to have something call on thread death. + for(size_t i = 0; i < m_TLSList->size(); i++) + delete m_TLSList->at(i); + + delete m_TLSList; + delete m_TLSListLock; + TlsFree(OSTLSHandle); } @@ -176,6 +184,13 @@ void SetTLSValue(uint64_t slot, void *value) { slots = new TLSData; TlsSetValue(OSTLSHandle, slots); + + // in the case where this thread is entirely new, we globally lock so we can + // store its data for shutdown (as we might not get notified of every thread + // that exits). This only happens once, so we take the hit of the lock. + m_TLSListLock->Lock(); + m_TLSList->push_back(slots); + m_TLSListLock->Unlock(); } if(slot - 1 >= slots->data.size()) diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index 3c3266e38..311cb94ce 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -962,7 +962,10 @@ Serialiser::~Serialiser() } for(size_t i = 0; i < m_Sections.size(); i++) + { SAFE_DELETE(m_Sections[i]->compressedReader); + SAFE_DELETE(m_Sections[i]); + } for(size_t i = 0; i < m_Chunks.size(); i++) { diff --git a/valgrind.supp b/valgrind.supp new file mode 100644 index 000000000..42e3aad1b --- /dev/null +++ b/valgrind.supp @@ -0,0 +1,275 @@ +# We don't care about problems in the ICD or loader +# Many of these could be false positives, since valgrind doesn't know about GPU access +{ + IntelVulkanAddr8 + Memcheck:Addr8 + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanAddr4 + Memcheck:Addr4 + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanAddr2 + Memcheck:Addr2 + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanAddr1 + Memcheck:Addr1 + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanCond + Memcheck:Cond + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanValue8 + Memcheck:Value8 + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanLeak + Memcheck:Leak + match-leak-kinds: all + ... + obj:*libvulkan_intel.so* +} +{ + IntelVulkanLeak + Memcheck:Leak + match-leak-kinds: all + ... + obj:*libvulkan.so* +} + +# Unknown cause but not important leak +{ + UnknownLeak1 + Memcheck:Leak + match-leak-kinds: all + fun:malloc + ... + fun:_dl_init +} + +# Try to suppress only access from mapped pointers, to avoid false negatives +{ + InitialStateMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + ... + fun:_ZN13WrappedVulkan22Serialise_InitialStateE10ResourceIdP12WrappedVkRes +} +{ + InitialStateMemcpy + Memcheck:Addr4 + fun:memcpy@@GLIBC_2.14 + ... + fun:_ZN13WrappedVulkan22Serialise_InitialStateE10ResourceIdP12WrappedVkRes +} +{ + InitialStateMemcpy + Memcheck:Addr2 + fun:memcpy@@GLIBC_2.14 + ... + fun:_ZN13WrappedVulkan22Serialise_InitialStateE10ResourceIdP12WrappedVkRes +} +{ + InitialStateMemcpy + Memcheck:Addr1 + fun:memcpy@@GLIBC_2.14 + ... + fun:_ZN13WrappedVulkan22Serialise_InitialStateE10ResourceIdP12WrappedVkRes +} +{ + DebugInitMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManagerC1EP13WrappedVulkanP10VkDevice_T +} +{ + UnmapMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan23Serialise_vkUnmapMemoryEP10SerialiserP10VkDevice_TP16VkDeviceMemory_T +} +{ + UnmapMemcpy + Memcheck:Addr4 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan23Serialise_vkUnmapMemoryEP10SerialiserP10VkDevice_TP16VkDeviceMemory_T +} +{ + UnmapMemcpy + Memcheck:Addr2 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan23Serialise_vkUnmapMemoryEP10SerialiserP10VkDevice_TP16VkDeviceMemory_T +} +{ + UnmapMemcpy + Memcheck:Addr1 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan23Serialise_vkUnmapMemoryEP10SerialiserP10VkDevice_TP16VkDeviceMemory_T +} +{ + FlushMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan35Serialise_vkFlushMappedMemoryRangesEP10SerialiserP10VkDevice_TjPK19VkMappedMemoryRange +} +{ + FlushMemcpy + Memcheck:Addr4 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan35Serialise_vkFlushMappedMemoryRangesEP10SerialiserP10VkDevice_TjPK19VkMappedMemoryRange +} +{ + FlushMemcpy + Memcheck:Addr2 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan35Serialise_vkFlushMappedMemoryRangesEP10SerialiserP10VkDevice_TjPK19VkMappedMemoryRange +} +{ + FlushMemcpy + Memcheck:Addr1 + fun:memcpy@@GLIBC_2.14 + fun:_ZN13WrappedVulkan35Serialise_vkFlushMappedMemoryRangesEP10SerialiserP10VkDevice_TjPK19VkMappedMemoryRange +} +{ + GetTextureDataMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} +{ + GetTextureDataMemcpy + Memcheck:Addr4 + fun:memcpy@@GLIBC_2.14 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} +{ + GetTextureDataMemcpy + Memcheck:Addr2 + fun:memcpy@@GLIBC_2.14 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} +{ + GetTextureDataMemcpy + Memcheck:Addr1 + fun:memcpy@@GLIBC_2.14 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} +{ + GetBufferDataMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager13GetBufferDataE10ResourceIdmmRSt6vectorIhSaIhEE +} +{ + GetBufferDataMemcpy + Memcheck:Addr4 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager13GetBufferDataE10ResourceIdmmRSt6vectorIhSaIhEE +} +{ + GetBufferDataMemcpy + Memcheck:Addr2 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager13GetBufferDataE10ResourceIdmmRSt6vectorIhSaIhEE +} +{ + GetBufferDataMemcpy + Memcheck:Addr1 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager13GetBufferDataE10ResourceIdmmRSt6vectorIhSaIhEE +} +{ + InitPostVSDataMemcpy + Memcheck:Addr8 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager17InitPostVSBuffersEj +} +{ + InitPostVSDataMemcpy + Memcheck:Addr4 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager17InitPostVSBuffersEj +} +{ + InitPostVSDataMemcpy + Memcheck:Addr2 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager17InitPostVSBuffersEj +} +{ + InitPostVSDataMemcpy + Memcheck:Addr1 + fun:memcpy@@GLIBC_2.14 + fun:_ZN18VulkanDebugManager17InitPostVSBuffersEj +} +# We read from mapped memory here rather than just memcpy'ing, have to suppress the whole thing +# near/far calculations +{ + InitPostVSDataRead + Memcheck:Addr4 + fun:_ZN18VulkanDebugManager17InitPostVSBuffersEj +} +# manual depth/stencil packing +{ + InitPostVSDataRead + Memcheck:Addr4 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} +{ + InitPostVSDataRead + Memcheck:Addr2 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} +{ + InitPostVSDataRead + Memcheck:Addr1 + fun:_ZN12VulkanReplay14GetTextureDataE10ResourceIdjj19FormatComponentTypebbffRm +} + +# Temporary leak - to be fixed, but has to happen upstream +{ + glslangLeaks + Memcheck:Leak + match-leak-kinds: all + ... + fun:_Z17InitSPIRVCompilerv +} + +# These are deliberate leaks, only once per program run, or once per API load +{ + GlobalLogfileString + Memcheck:Leak + match-leak-kinds: reachable + fun:_Znwm + fun:_ZL7logfilev +} +{ + GlobalLogfileString2 + Memcheck:Leak + match-leak-kinds: reachable + fun:_Znwm + ... + fun:_Z15rdclog_filenamePKc +} +{ + LoadVulkanModule + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7Process10LoadModuleEPKc + fun:_Z25Vulkan_CreateReplayDevicePKcPP13IReplayDriver +}