Changeset View
Changeset View
Standalone View
Standalone View
source/ps/Profiler2.cpp
/* Copyright (C) 2021 Wildfire Games. | /* Copyright (C) 2021 Wildfire Games. | ||||
Lint: Inaccurate Copyright Year: Inaccurate Copyright Year | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* "Software"), to deal in the Software without restriction, including | * "Software"), to deal in the Software without restriction, including | ||||
* without limitation the rights to use, copy, modify, merge, publish, | * without limitation the rights to use, copy, modify, merge, publish, | ||||
* distribute, sublicense, and/or sell copies of the Software, and to | * distribute, sublicense, and/or sell copies of the Software, and to | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
▲ Show 20 Lines • Show All 318 Lines • ▼ Show 20 Lines | void CProfiler2::ThreadStorage::Write(EItem type, const void* item, u32 itemSize) | ||||
if (m_HeldDepth > 0) | if (m_HeldDepth > 0) | ||||
{ | { | ||||
WriteHold(type, item, itemSize); | WriteHold(type, item, itemSize); | ||||
return; | return; | ||||
} | } | ||||
// See m_BufferPos0 etc for comments on synchronisation | // See m_BufferPos0 etc for comments on synchronisation | ||||
u32 size = 1 + itemSize; | u32 size = 1 + itemSize; | ||||
u32 start = m_BufferPos0; | u32 start = m_BufferPos0.load(std::memory_order_relaxed); | ||||
if (start + size > BUFFER_SIZE) | if (start + size > BUFFER_SIZE) | ||||
{ | { | ||||
// The remainder of the buffer is too small - fill the rest | // The remainder of the buffer is too small - fill the rest | ||||
// with NOPs then start from offset 0, so we don't have to | // with NOPs then start from offset 0, so we don't have to | ||||
// bother splitting the real item across the end of the buffer | // bother splitting the real item across the end of the buffer | ||||
m_BufferPos0 = size; | m_BufferPos0.store(size, std::memory_order_release); | ||||
COMPILER_FENCE; // must write m_BufferPos0 before m_Buffer | |||||
memset(m_Buffer + start, 0, BUFFER_SIZE - start); | memset(m_Buffer + start, 0, BUFFER_SIZE - start); | ||||
start = 0; | start = 0; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
m_BufferPos0 = start + size; | m_BufferPos0.store(start + size, std::memory_order_release); | ||||
COMPILER_FENCE; // must write m_BufferPos0 before m_Buffer | |||||
} | } | ||||
m_Buffer[start] = (u8)type; | m_Buffer[start] = (u8)type; | ||||
memcpy(&m_Buffer[start + 1], item, itemSize); | memcpy(&m_Buffer[start + 1], item, itemSize); | ||||
COMPILER_FENCE; // must write m_BufferPos1 after m_Buffer | m_BufferPos1.store(start + size, std::memory_order_release); | ||||
Not Done Inline ActionsIs there an include that needs to be removed for this? Stan: Is there an include that needs to be removed for this? | |||||
Done Inline ActionsNo lib/code_annotation.h was not included. phosit: No `lib/code_annotation.h` was not included. | |||||
m_BufferPos1 = start + size; | |||||
} | } | ||||
void CProfiler2::ThreadStorage::WriteHold(EItem type, const void* item, u32 itemSize) | void CProfiler2::ThreadStorage::WriteHold(EItem type, const void* item, u32 itemSize) | ||||
{ | { | ||||
u32 size = 1 + itemSize; | u32 size = 1 + itemSize; | ||||
if (m_HoldBuffers[m_HeldDepth - 1].pos + size > CProfiler2::HOLD_BUFFER_SIZE) | if (m_HoldBuffers[m_HeldDepth - 1].pos + size > CProfiler2::HOLD_BUFFER_SIZE) | ||||
return; // we held on too much data, ignore the rest | return; // we held on too much data, ignore the rest | ||||
m_HoldBuffers[m_HeldDepth - 1].buffer[m_HoldBuffers[m_HeldDepth - 1].pos] = (u8)type; | m_HoldBuffers[m_HeldDepth - 1].buffer[m_HoldBuffers[m_HeldDepth - 1].pos] = (u8)type; | ||||
memcpy(&m_HoldBuffers[m_HeldDepth - 1].buffer[m_HoldBuffers[m_HeldDepth - 1].pos + 1], item, itemSize); | memcpy(&m_HoldBuffers[m_HeldDepth - 1].buffer[m_HoldBuffers[m_HeldDepth - 1].pos + 1], item, itemSize); | ||||
m_HoldBuffers[m_HeldDepth - 1].pos += size; | m_HoldBuffers[m_HeldDepth - 1].pos += size; | ||||
} | } | ||||
std::string CProfiler2::ThreadStorage::GetBuffer() | std::string CProfiler2::ThreadStorage::GetBuffer() | ||||
{ | { | ||||
// Called from an arbitrary thread (not the one writing to the buffer). | // Called from an arbitrary thread (not the one writing to the buffer). | ||||
// | // | ||||
// See comments on m_BufferPos0 etc. | // See comments on m_BufferPos0 etc. | ||||
std::shared_ptr<u8> buffer(new u8[BUFFER_SIZE], ArrayDeleter()); | std::shared_ptr<u8> buffer(new u8[BUFFER_SIZE], ArrayDeleter()); | ||||
u32 pos1 = m_BufferPos1; | u32 pos1 = m_BufferPos1.load(std::memory_order_acquire); | ||||
COMPILER_FENCE; // must read m_BufferPos1 before m_Buffer | |||||
memcpy(buffer.get(), m_Buffer, BUFFER_SIZE); | memcpy(buffer.get(), m_Buffer, BUFFER_SIZE); | ||||
COMPILER_FENCE; // must read m_BufferPos0 after m_Buffer | u32 pos0 = m_BufferPos0.load(std::memory_order_acquire); | ||||
u32 pos0 = m_BufferPos0; | |||||
// The range [pos1, pos0) modulo BUFFER_SIZE is invalid, so concatenate the rest of the buffer | // The range [pos1, pos0) modulo BUFFER_SIZE is invalid, so concatenate the rest of the buffer | ||||
if (pos1 <= pos0) // invalid range is in the middle of the buffer | if (pos1 <= pos0) // invalid range is in the middle of the buffer | ||||
return std::string(buffer.get()+pos0, buffer.get()+BUFFER_SIZE) + std::string(buffer.get(), buffer.get()+pos1); | return std::string(buffer.get()+pos0, buffer.get()+BUFFER_SIZE) + std::string(buffer.get(), buffer.get()+pos1); | ||||
else // invalid wrap is wrapped around the end/start buffer | else // invalid wrap is wrapped around the end/start buffer | ||||
return std::string(buffer.get()+pos0, buffer.get()+pos1); | return std::string(buffer.get()+pos0, buffer.get()+pos1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 297 Lines • ▼ Show 20 Lines | if (m_HeldDepth > 1) | ||||
memcpy(&target.buffer[target.pos], copied.buffer, copied.pos); | memcpy(&target.buffer[target.pos], copied.buffer, copied.pos); | ||||
target.pos += copied.pos; | target.pos += copied.pos; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
u32 size = m_HoldBuffers[m_HeldDepth - 1].pos; | u32 size = m_HoldBuffers[m_HeldDepth - 1].pos; | ||||
u32 start = m_BufferPos0; | u32 start = m_BufferPos0.load(std::memory_order_relaxed); | ||||
if (start + size > BUFFER_SIZE) | if (start + size > BUFFER_SIZE) | ||||
{ | { | ||||
m_BufferPos0 = size; | m_BufferPos0.store(size, std::memory_order_release); | ||||
COMPILER_FENCE; | |||||
memset(m_Buffer + start, 0, BUFFER_SIZE - start); | memset(m_Buffer + start, 0, BUFFER_SIZE - start); | ||||
start = 0; | start = 0; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
m_BufferPos0 = start + size; | m_BufferPos0.store(start + size, std::memory_order_release); | ||||
COMPILER_FENCE; // must write m_BufferPos0 before m_Buffer | |||||
} | } | ||||
memcpy(&m_Buffer[start], m_HoldBuffers[m_HeldDepth - 1].buffer, size); | memcpy(&m_Buffer[start], m_HoldBuffers[m_HeldDepth - 1].buffer, size); | ||||
COMPILER_FENCE; // must write m_BufferPos1 after m_Buffer | m_BufferPos1.store(start + size, std::memory_order_release); | ||||
m_BufferPos1 = start + size; | |||||
} | } | ||||
m_HeldDepth--; | m_HeldDepth--; | ||||
} | } | ||||
void CProfiler2::ThreadStorage::ThrowawayHoldBuffer() | void CProfiler2::ThreadStorage::ThrowawayHoldBuffer() | ||||
{ | { | ||||
if (!m_HeldDepth) | if (!m_HeldDepth) | ||||
return; | return; | ||||
m_HeldDepth--; | m_HeldDepth--; | ||||
▲ Show 20 Lines • Show All 274 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
Inaccurate Copyright Year