Changeset View
Changeset View
Standalone View
Standalone View
source/ps/Profiler2.cpp
Show First 20 Lines • Show All 306 Lines • ▼ Show 20 Lines | |||||
void CProfiler2::RemoveThreadStorage(ThreadStorage* storage) | void CProfiler2::RemoveThreadStorage(ThreadStorage* storage) | ||||
{ | { | ||||
std::lock_guard<std::mutex> lock(m_Mutex); | std::lock_guard<std::mutex> lock(m_Mutex); | ||||
m_Threads.erase(std::find_if(m_Threads.begin(), m_Threads.end(), [storage](const std::unique_ptr<ThreadStorage>& s) { return s.get() == storage; })); | m_Threads.erase(std::find_if(m_Threads.begin(), m_Threads.end(), [storage](const std::unique_ptr<ThreadStorage>& s) { return s.get() == storage; })); | ||||
} | } | ||||
CProfiler2::ThreadStorage::ThreadStorage(CProfiler2& profiler, const std::string& name) : | CProfiler2::ThreadStorage::ThreadStorage(CProfiler2& profiler, const std::string& name) : | ||||
m_Profiler(profiler), m_Name(name), m_BufferPos0(0), m_BufferPos1(0), m_LastTime(timer_Time()), m_HeldDepth(0) | m_Profiler(profiler), m_Name(name), m_LastTime(timer_Time()), m_HeldDepth(0) | ||||
{ | { | ||||
m_Buffer = new u8[BUFFER_SIZE]; | m_Buffer = new u8[BUFFER_SIZE]; | ||||
memset(m_Buffer, ITEM_NOP, BUFFER_SIZE); | memset(m_Buffer, ITEM_NOP, BUFFER_SIZE); | ||||
} | } | ||||
CProfiler2::ThreadStorage::~ThreadStorage() | CProfiler2::ThreadStorage::~ThreadStorage() | ||||
{ | { | ||||
delete[] m_Buffer; | delete[] m_Buffer; | ||||
} | } | ||||
void CProfiler2::ThreadStorage::Write(EItem type, const void* item, u32 itemSize) | 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 RingBufferSpan etc for comments on synchronisation | ||||
u32 size = 1 + itemSize; | u32 size = 1 + itemSize; | ||||
u32 start = m_BufferPos0; | u32 start = m_ValidRange.begin.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_ValidRange.begin.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_ValidRange.begin.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_ValidRange.end.store(start + size, std::memory_order_release); | ||||
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_ValidRange.end.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_ValidRange.begin.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 298 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_ValidRange.begin.load(std::memory_order_relaxed); | ||||
if (start + size > BUFFER_SIZE) | if (start + size > BUFFER_SIZE) | ||||
{ | { | ||||
m_BufferPos0 = size; | m_ValidRange.begin.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_ValidRange.begin.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_ValidRange.end.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
Is there an include that needs to be removed for this?