Fix errors and leaks found by valgrind on linux replay host

* These are some leaks, some mismatched new/deletes and some uninit'd
  values. Mostly the leaks are what we care about so that the replay
  host can be kept alive for a long time rather than needing to be
  constantly restarted.
* Also added a valgrind suppression file to suppress some of the false
  positives I ran into while testing.
This commit is contained in:
baldurk
2016-07-14 20:37:32 +02:00
parent a7eca41a81
commit 80bdfe6058
14 changed files with 364 additions and 28 deletions
+1 -1
View File
@@ -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;
+11
View File
@@ -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;
+6
View File
@@ -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];
+1
View File
@@ -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);
}
+3 -5
View File
@@ -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();
+7 -5
View File
@@ -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)
+8
View File
@@ -328,6 +328,8 @@ private:
struct BakedCmdBufferInfo
{
BakedCmdBufferInfo() : draw(NULL) {}
~BakedCmdBufferInfo() { SAFE_DELETE(draw); }
vector<FetchAPIEvent> curEvents;
vector<DebugMessage> debugMessages;
list<VulkanDrawcallTreeNode *> 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<DescriptorSetSlot *> currentBindings;
};
+5 -7
View File
@@ -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)
{
+1 -2
View File
@@ -108,7 +108,7 @@ public:
vector<DebugMessage> 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<uint64_t, OutputWindow> m_OutputWindows;
uint64_t m_OutputWinID;
@@ -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));
+19 -4
View File
@@ -125,21 +125,29 @@ struct TLSData
vector<void *> data;
};
static CriticalSection *m_TLSListLock = NULL;
static vector<TLSData *> *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<TLSData *>();
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())
+19 -4
View File
@@ -130,19 +130,27 @@ struct TLSData
vector<void *> data;
};
static CriticalSection *m_TLSListLock = NULL;
static vector<TLSData *> *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<TLSData *>();
}
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())
+3
View File
@@ -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++)
{
+275
View File
@@ -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
}