mirror of
https://github.com/wolfpld/tracy.git
synced 2026-06-16 12:18:59 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ea4a326f3 | ||
|
|
62957310a0 |
77
FAQ.md
77
FAQ.md
@@ -1,77 +0,0 @@
|
||||
# A quick tracy FAQ
|
||||
|
||||
### I already use VTune/perf/Very Sleepy/callgrind/MSVC profiler.
|
||||
|
||||
These are statistical profilers, which can be used to find hot spots in the code. This is very useful, but it won't show you the underlying reason for semi-random frame stutter that may occur every couple of seconds.
|
||||
|
||||
### You can use Telemetry for that.
|
||||
|
||||
Telemetry license costs about 8000 $ per year. Tracy is open source software. Telemetry doesn't have Lua bindings.
|
||||
|
||||
### You can use the free Brofiler. Crytek does use it, so it has to be good.
|
||||
|
||||
After a cursory look at the Brofiler code I can tell that the timer resolution there is at 300 ns. Tracy can achieve 5 ns timer resolution. Brofiler event logging infrastructure seems to be over-engineered. Brofiler can't track lock contention, nor does it have Lua bindings.
|
||||
|
||||
### So tracy is supposedly faster?
|
||||
|
||||
My measurements show that logging a single zone with tracy takes only 15 ns. In theory, if the program was doing nothing else, tracy should be able to log 66 million zones per second.
|
||||
|
||||
### Bullshit, RAD is advertising that they are able only to log about a million zones, over the network nevertheless: "Capture over a million timing zones per second in real-time!"
|
||||
|
||||
Tracy can perform network transfer of 15 million zones per second. Should the client and server be on separate machines, this number will be even higher, but you will need more than a gigabit link to achieve the maximum throughput. [Click here for a video of a max-throughput capture.](https://www.youtube.com/watch?v=DSMIHShKGAc)
|
||||
|
||||
### Can I connect to my application at any time and start profiling at this moment?
|
||||
|
||||
No, all events are registered from the beginning of program execution and are waiting in a queue.
|
||||
|
||||
### Am I seeing correctly that the profiler allocates one gigabyte of memory per second?
|
||||
|
||||
Only in extreme cases. Normal usage has much lower memory pressure.
|
||||
|
||||
### Why do you do magic with the static initialization order? Everyone says that's a bad practice.
|
||||
|
||||
It allows tracking construction of static objects and memory allocations performed before main() is entered.
|
||||
|
||||
### There's no support for consoles.
|
||||
|
||||
Welp. But there's mobile support.
|
||||
|
||||
### I do need console support.
|
||||
|
||||
The code is open. Write your own, then send a patch.
|
||||
|
||||
### I don't believe you can capture a zone in 15 ns. Show me the code!
|
||||
|
||||
Following is the annotated assembly code (generated from C++ sources) that's responsible for logging start of the zone:
|
||||
|
||||
```
|
||||
call qword ptr [__imp_GetCurrentThreadId]
|
||||
mov r14d,eax
|
||||
mov qword ptr [rsp+0F0h],r14 // save thread id for later use
|
||||
mov r12d,10h
|
||||
mov rax,qword ptr gs:[58h] // TLS
|
||||
mov r15,qword ptr [rax] // queue address
|
||||
mov rdi,qword ptr [r12+r15] // data address
|
||||
mov rbp,qword ptr [rdi+20h] // buffer counter
|
||||
mov rbx,rbp
|
||||
and ebx,7Fh // 128 item buffer
|
||||
jne Application::InnerLoop+66h --+
|
||||
mov rdx,rbp |
|
||||
mov rcx,rdi |
|
||||
call enqueue_begin_alloc | // reclaim/alloc next buffer
|
||||
shl rbx,5 <---------------------+ // buffer items are 32 bytes
|
||||
add rbx,qword ptr [rdi+40h]
|
||||
mov byte ptr [rbx],4 // queue item type
|
||||
rdtscp
|
||||
mov dword ptr [rbx+19h],ecx // cpu id
|
||||
shl rdx,20h
|
||||
or rax,rdx // 64 bit timestamp
|
||||
mov qword ptr [rbx+1],rax
|
||||
mov qword ptr [rbx+9],r14 // thread id
|
||||
lea rax,[__tracy_source_location] // static struct address
|
||||
mov qword ptr [rbx+11h],rax
|
||||
lea rax,[rbp+1] // increment buffer counter
|
||||
mov qword ptr [rdi+20h],rax
|
||||
```
|
||||
|
||||
There's also a second code block, for the end of the zone. It's similar, but a bit smaller, as it can use some of the variables that were retrieved above.
|
||||
44
NEWS
44
NEWS
@@ -1,44 +0,0 @@
|
||||
v0.2 (2018-04-05)
|
||||
-----------------
|
||||
|
||||
- Fixed broken TRACY_NO_EXIT behavior.
|
||||
- Visual refresh (new color scheme).
|
||||
- Added optional support for live in-depth zone analysis.
|
||||
- Ability to search for zones matching a query.
|
||||
- Histogram of zone time spans.
|
||||
- List occurrences of a zone, grouped by thread, or by user text.
|
||||
- Zone groups can be selected and highlighted on histogram graph.
|
||||
- Support for linear and logarithmic display of time and values.
|
||||
- Histogram bins can show zone counts or total execution time.
|
||||
- Listed zones can be narrowed down by data range selection on histogram.
|
||||
- Separation of server data handling code from the visualisation.
|
||||
- Implementation of a command line capture utility.
|
||||
- Support libraries have been updated.
|
||||
- Fixed an issue that prevented de-duplication of source location payloads.
|
||||
- Fixed an issue that prevented the ability to disable threads in settings
|
||||
menu, if two threads had the same name.
|
||||
- Performance optimizations.
|
||||
- Visual clean up of the settings menu.
|
||||
- Zone info windows improvements.
|
||||
- Visual improvements to zone info window child list.
|
||||
- Zone info windows now show zone thread.
|
||||
- Display zone stack trace.
|
||||
- Hide pause/resume button if there's no data connection (i.e. trace was
|
||||
loaded from file).
|
||||
- Source location statistics view has been added.
|
||||
- Fixed crash when a saved trace was opened, but no trace capture session
|
||||
was performed before.
|
||||
- Standalone server will now open trace files passed as an argument to the
|
||||
executable.
|
||||
- Fix possible crash in SetThreadName, that could happen if TLS init was
|
||||
delayed until first use of thread local variable.
|
||||
- Store full thread name if pthreads (with 15 character name limit) are
|
||||
used.
|
||||
- Properly handle unaligned memory access (no performance impact).
|
||||
- Fixed broken lock identifiers in try_lock().
|
||||
|
||||
|
||||
v0.1 (2017-12-18)
|
||||
-----------------
|
||||
|
||||
- Initial release.
|
||||
@@ -20,10 +20,6 @@ The following compilers are supported:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
[Introduction to tracy](https://www.youtube.com/watch?v=fB5B46lbapc)
|
||||
[A quick FAQ.](FAQ.md)
|
||||
[List of changes.](NEWS)
|
||||
|
||||
### High-level overview
|
||||
|
||||

|
||||
@@ -91,8 +87,6 @@ Fast navigation in large data set and correlation of zones with what was happeni
|
||||
|
||||
The easiest way to get going is to build the standalone server, available in the `standalone` directory. You can connect to localhost or remote clients and view the collected data right away.
|
||||
|
||||
If you prefer to inspect the data only after a trace has been performed, you may use the command line utility in the `capture` directory. It will save a data dump that may be later opened in the graphical viewer application.
|
||||
|
||||
Alternatively, you may want to embed the server in your application, the same which is running the client part of tracy. Doing so requires that you also include the `server` and `imgui` directories. Include the `tracy/server/TracyView.hpp` header file, create an instance of the `tracy::View` class and call its `Draw()` method every frame. Unfortunately, there's also the hard part - you need to integrate the imgui library into the innards of your program. How to do so is outside the scope of this document.
|
||||
|
||||
#### Lua support
|
||||
@@ -130,5 +124,3 @@ While the data collection is very lightweight, it is not completely free. Each r
|
||||
Lua instrumentation needs to perform additional work (including memory allocation) to store source location. This approximately doubles the data collection cost.
|
||||
|
||||
You may use named colors predefined in `common/TracyColor.hpp` (included by `Tracy.hpp`). Visual reference: [wikipedia](https://en.wikipedia.org/wiki/X11_color_names).
|
||||
|
||||
Tracy server will perform statistical data collection on the fly, if the macro `TRACY_NO_STATISTICS` is not defined. This allows extended analysis of the trace (for example, you can perform a live search for matching zones) at a small CPU processing cost and a considerable memory usage increase (at least 10 bytes per zone).
|
||||
|
||||
55
TracyLua.hpp
55
TracyLua.hpp
@@ -101,7 +101,6 @@ static inline void LuaRemove( char* script )
|
||||
#else
|
||||
|
||||
#include "common/TracyColor.hpp"
|
||||
#include "common/TracyAlign.hpp"
|
||||
#include "common/TracySystem.hpp"
|
||||
#include "client/TracyProfiler.hpp"
|
||||
|
||||
@@ -144,16 +143,10 @@ static inline int LuaZoneBegin( lua_State* L )
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneBeginAllocSrcLoc );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( item->zoneBegin.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneBegin.thread, GetThreadHandle() );
|
||||
MemWrite( &item->zoneBegin.srcloc, (uint64_t)ptr );
|
||||
item->hdr.type = QueueType::ZoneBeginAllocSrcLoc;
|
||||
item->zoneBegin.time = Profiler::GetTime( item->zoneBegin.cpu );
|
||||
item->zoneBegin.thread = GetThreadHandle();
|
||||
item->zoneBegin.srcloc = (uint64_t)ptr;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
return 0;
|
||||
}
|
||||
@@ -195,16 +188,10 @@ static inline int LuaZoneBeginN( lua_State* L )
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneBeginAllocSrcLoc );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( item->zoneBegin.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneBegin.thread, GetThreadHandle() );
|
||||
MemWrite( &item->zoneBegin.srcloc, (uint64_t)ptr );
|
||||
item->hdr.type = QueueType::ZoneBeginAllocSrcLoc;
|
||||
item->zoneBegin.time = Profiler::GetTime( item->zoneBegin.cpu );
|
||||
item->zoneBegin.thread = GetThreadHandle();
|
||||
item->zoneBegin.srcloc = (uint64_t)ptr;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
return 0;
|
||||
}
|
||||
@@ -215,15 +202,9 @@ static inline int LuaZoneEnd( lua_State* L )
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneEnd );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneEnd.time, Profiler::GetTime( item->zoneEnd.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneEnd.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneEnd.thread, GetThreadHandle() );
|
||||
item->hdr.type = QueueType::ZoneEnd;
|
||||
item->zoneEnd.time = Profiler::GetTime( item->zoneEnd.cpu );
|
||||
item->zoneEnd.thread = GetThreadHandle();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
return 0;
|
||||
}
|
||||
@@ -240,9 +221,9 @@ static inline int LuaZoneText( lua_State* L )
|
||||
ptr[size] = '\0';
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneText );
|
||||
MemWrite( &item->zoneText.thread, GetThreadHandle() );
|
||||
MemWrite( &item->zoneText.text, (uint64_t)ptr );
|
||||
item->hdr.type = QueueType::ZoneText;
|
||||
item->zoneText.thread = GetThreadHandle();
|
||||
item->zoneText.text = (uint64_t)ptr;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
return 0;
|
||||
}
|
||||
@@ -259,10 +240,10 @@ static inline int LuaMessage( lua_State* L )
|
||||
ptr[size] = '\0';
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::Message );
|
||||
MemWrite( &item->message.time, Profiler::GetTime() );
|
||||
MemWrite( &item->message.thread, GetThreadHandle() );
|
||||
MemWrite( &item->message.text, (uint64_t)ptr );
|
||||
item->hdr.type = QueueType::Message;
|
||||
item->message.time = Profiler::GetTime();
|
||||
item->message.thread = GetThreadHandle();
|
||||
item->message.text = (uint64_t)ptr;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "Tracy.hpp"
|
||||
#include "client/TracyProfiler.hpp"
|
||||
#include "common/TracyAlign.hpp"
|
||||
#include "common/TracyAlloc.hpp"
|
||||
|
||||
#define TracyGpuContext tracy::s_gpuCtx.ptr = (tracy::GpuCtx*)tracy::tracy_malloc( sizeof( tracy::GpuCtx ) ); new(tracy::s_gpuCtx.ptr) tracy::GpuCtx;
|
||||
@@ -54,12 +53,12 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::GpuNewContext );
|
||||
MemWrite( &item->gpuNewContext.cpuTime, tcpu );
|
||||
MemWrite( &item->gpuNewContext.gpuTime, tgpu );
|
||||
MemWrite( &item->gpuNewContext.thread, GetThreadHandle() );
|
||||
MemWrite( &item->gpuNewContext.context, m_context );
|
||||
MemWrite( &item->gpuNewContext.accuracyBits, (uint8_t)bits );
|
||||
item->hdr.type = QueueType::GpuNewContext;
|
||||
item->gpuNewContext.cpuTime = tcpu;
|
||||
item->gpuNewContext.gpuTime = tgpu;
|
||||
item->gpuNewContext.thread = GetThreadHandle();
|
||||
item->gpuNewContext.context = m_context;
|
||||
item->gpuNewContext.accuracyBits = bits;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -98,9 +97,9 @@ public:
|
||||
glGetQueryObjectui64v( m_query[m_tail], GL_QUERY_RESULT, &time );
|
||||
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::GpuTime );
|
||||
MemWrite( &item->gpuTime.gpuTime, (int64_t)time );
|
||||
MemWrite( &item->gpuTime.context, m_context );
|
||||
item->hdr.type = QueueType::GpuTime;
|
||||
item->gpuTime.gpuTime = (int64_t)time;
|
||||
item->gpuTime.context = m_context;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
m_tail = ( m_tail + 1 ) % QueryCount;
|
||||
}
|
||||
@@ -111,10 +110,10 @@ public:
|
||||
int64_t tcpu = Profiler::GetTime();
|
||||
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::GpuResync );
|
||||
MemWrite( &item->gpuResync.cpuTime, tcpu );
|
||||
MemWrite( &item->gpuResync.gpuTime, tgpu );
|
||||
MemWrite( &item->gpuResync.context, m_context );
|
||||
item->hdr.type = QueueType::GpuResync;
|
||||
item->gpuResync.cpuTime = tcpu;
|
||||
item->gpuResync.gpuTime = tgpu;
|
||||
item->gpuResync.context = m_context;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
@@ -153,10 +152,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::GpuZoneBegin );
|
||||
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
||||
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
||||
MemWrite( &item->gpuZoneBegin.context, s_gpuCtx.ptr->GetId() );
|
||||
item->hdr.type = QueueType::GpuZoneBegin;
|
||||
item->gpuZoneBegin.cpuTime = Profiler::GetTime();
|
||||
item->gpuZoneBegin.srcloc = (uint64_t)srcloc;
|
||||
item->gpuZoneBegin.context = s_gpuCtx.ptr->GetId();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -168,9 +167,9 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::GpuZoneEnd );
|
||||
MemWrite( &item->gpuZoneEnd.cpuTime, Profiler::GetTime() );
|
||||
MemWrite( &item->gpuZoneEnd.context, s_gpuCtx.ptr->GetId() );
|
||||
item->hdr.type = QueueType::GpuZoneEnd;
|
||||
item->gpuZoneEnd.cpuTime = Profiler::GetTime();
|
||||
item->gpuZoneEnd.context = s_gpuCtx.ptr->GetId();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CFLAGS +=
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++14
|
||||
DEFINES += -DTRACY_NO_STATISTICS
|
||||
DEFINES +=
|
||||
INCLUDES :=
|
||||
LIBS := -lpthread
|
||||
IMAGE := capture
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<PreprocessorDefinitions>TRACY_NO_STATISTICS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -116,7 +116,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<PreprocessorDefinitions>TRACY_NO_STATISTICS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -136,7 +136,6 @@
|
||||
<ClCompile Include="..\..\src\getopt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\common\TracyAlign.hpp" />
|
||||
<ClInclude Include="..\..\..\common\TracyAlloc.hpp" />
|
||||
<ClInclude Include="..\..\..\common\TracyColor.hpp" />
|
||||
<ClInclude Include="..\..\..\common\TracyForceInline.hpp" />
|
||||
|
||||
@@ -95,8 +95,5 @@
|
||||
<ClInclude Include="..\..\src\getopt.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\common\TracyAlign.hpp">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -166,7 +166,7 @@ int main( int argc, char** argv )
|
||||
|
||||
printf( "\nFrames: %" PRIu64 "\nTime span: %s\nZones: %s\nSaving trace...", worker.GetFrameCount(), TimeToString( worker.GetLastTime() - worker.GetFrameBegin( 0 ) ), RealToString( worker.GetZoneCount(), true ) );
|
||||
fflush( stdout );
|
||||
auto f = std::unique_ptr<tracy::FileWrite>( tracy::FileWrite::Open( output ) );
|
||||
auto f = tracy::FileWrite::Open( output );
|
||||
if( f )
|
||||
{
|
||||
worker.Write( *f );
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <limits>
|
||||
|
||||
#include "../common/TracySystem.hpp"
|
||||
#include "../common/TracyAlign.hpp"
|
||||
#include "TracyProfiler.hpp"
|
||||
|
||||
namespace tracy
|
||||
@@ -26,10 +25,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
|
||||
MemWrite( &item->lockAnnounce.id, m_id );
|
||||
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
|
||||
MemWrite( &item->lockAnnounce.type, LockType::Lockable );
|
||||
item->hdr.type = QueueType::LockAnnounce;
|
||||
item->lockAnnounce.id = m_id;
|
||||
item->lockAnnounce.lckloc = (uint64_t)srcloc;
|
||||
item->lockAnnounce.type = LockType::Lockable;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -44,11 +43,11 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockWait );
|
||||
MemWrite( &item->lockWait.id, m_id );
|
||||
MemWrite( &item->lockWait.thread, thread );
|
||||
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
||||
MemWrite( &item->lockWait.type, LockType::Lockable );
|
||||
item->hdr.type = QueueType::LockWait;
|
||||
item->lockWait.id = m_id;
|
||||
item->lockWait.thread = thread;
|
||||
item->lockWait.time = Profiler::GetTime();
|
||||
item->lockWait.type = LockType::Lockable;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -59,10 +58,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockObtain );
|
||||
MemWrite( &item->lockObtain.id, m_id );
|
||||
MemWrite( &item->lockObtain.thread, thread );
|
||||
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockObtain;
|
||||
item->lockObtain.id = m_id;
|
||||
item->lockObtain.thread = thread;
|
||||
item->lockObtain.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
@@ -75,10 +74,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockRelease );
|
||||
MemWrite( &item->lockRelease.id, m_id );
|
||||
MemWrite( &item->lockRelease.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockRelease;
|
||||
item->lockRelease.id = m_id;
|
||||
item->lockRelease.thread = GetThreadHandle();
|
||||
item->lockRelease.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -91,10 +90,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockObtain );
|
||||
MemWrite( &item->lockObtain.id, m_id );
|
||||
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockObtain;
|
||||
item->lockObtain.id = (uint64_t)&m_lockable;
|
||||
item->lockObtain.thread = GetThreadHandle();
|
||||
item->lockObtain.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
return ret;
|
||||
@@ -106,10 +105,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockMark );
|
||||
MemWrite( &item->lockMark.id, m_id );
|
||||
MemWrite( &item->lockMark.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );
|
||||
item->hdr.type = QueueType::LockMark;
|
||||
item->lockMark.id = m_id;
|
||||
item->lockMark.thread = GetThreadHandle();
|
||||
item->lockMark.srcloc = (uint64_t)srcloc;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -132,10 +131,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
|
||||
MemWrite( &item->lockAnnounce.id, m_id );
|
||||
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
|
||||
MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );
|
||||
item->hdr.type = QueueType::LockAnnounce;
|
||||
item->lockAnnounce.id = m_id;
|
||||
item->lockAnnounce.lckloc = (uint64_t)srcloc;
|
||||
item->lockAnnounce.type = LockType::SharedLockable;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -150,11 +149,11 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockWait );
|
||||
MemWrite( &item->lockWait.id, m_id );
|
||||
MemWrite( &item->lockWait.thread, thread );
|
||||
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
||||
MemWrite( &item->lockWait.type, LockType::SharedLockable );
|
||||
item->hdr.type = QueueType::LockWait;
|
||||
item->lockWait.id = m_id;
|
||||
item->lockWait.thread = thread;
|
||||
item->lockWait.time = Profiler::GetTime();
|
||||
item->lockWait.type = LockType::SharedLockable;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -165,10 +164,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockObtain );
|
||||
MemWrite( &item->lockObtain.id, m_id );
|
||||
MemWrite( &item->lockObtain.thread, thread );
|
||||
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockObtain;
|
||||
item->lockObtain.id = m_id;
|
||||
item->lockObtain.thread = thread;
|
||||
item->lockObtain.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
@@ -181,10 +180,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockRelease );
|
||||
MemWrite( &item->lockRelease.id, m_id );
|
||||
MemWrite( &item->lockRelease.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockRelease;
|
||||
item->lockRelease.id = m_id;
|
||||
item->lockRelease.thread = GetThreadHandle();
|
||||
item->lockRelease.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -197,10 +196,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockObtain );
|
||||
MemWrite( &item->lockObtain.id, m_id );
|
||||
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockObtain;
|
||||
item->lockObtain.id = (uint64_t)&m_lockable;
|
||||
item->lockObtain.thread = GetThreadHandle();
|
||||
item->lockObtain.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
return ret;
|
||||
@@ -214,11 +213,11 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockSharedWait );
|
||||
MemWrite( &item->lockWait.id, m_id );
|
||||
MemWrite( &item->lockWait.thread, thread );
|
||||
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
||||
MemWrite( &item->lockWait.type, LockType::SharedLockable );
|
||||
item->hdr.type = QueueType::LockSharedWait;
|
||||
item->lockWait.id = m_id;
|
||||
item->lockWait.thread = thread;
|
||||
item->lockWait.time = Profiler::GetTime();
|
||||
item->lockWait.type = LockType::SharedLockable;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -229,10 +228,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockSharedObtain );
|
||||
MemWrite( &item->lockObtain.id, m_id );
|
||||
MemWrite( &item->lockObtain.thread, thread );
|
||||
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockSharedObtain;
|
||||
item->lockObtain.id = m_id;
|
||||
item->lockObtain.thread = thread;
|
||||
item->lockObtain.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
@@ -245,10 +244,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockSharedRelease );
|
||||
MemWrite( &item->lockRelease.id, m_id );
|
||||
MemWrite( &item->lockRelease.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockSharedRelease;
|
||||
item->lockRelease.id = m_id;
|
||||
item->lockRelease.thread = GetThreadHandle();
|
||||
item->lockRelease.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -261,10 +260,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockSharedObtain );
|
||||
MemWrite( &item->lockObtain.id, m_id );
|
||||
MemWrite( &item->lockObtain.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockObtain.time, Profiler::GetTime() );
|
||||
item->hdr.type = QueueType::LockSharedObtain;
|
||||
item->lockObtain.id = (uint64_t)&m_lockable;
|
||||
item->lockObtain.thread = GetThreadHandle();
|
||||
item->lockObtain.time = Profiler::GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
return ret;
|
||||
@@ -276,10 +275,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::LockMark );
|
||||
MemWrite( &item->lockMark.id, m_id );
|
||||
MemWrite( &item->lockMark.thread, GetThreadHandle() );
|
||||
MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );
|
||||
item->hdr.type = QueueType::LockMark;
|
||||
item->lockMark.id = m_id;
|
||||
item->lockMark.thread = GetThreadHandle();
|
||||
item->lockMark.srcloc = (uint64_t)srcloc;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/TracyAlign.hpp"
|
||||
#include "../common/TracyProtocol.hpp"
|
||||
#include "../common/TracySocket.hpp"
|
||||
#include "../common/TracySystem.hpp"
|
||||
@@ -181,12 +180,12 @@ void Profiler::Worker()
|
||||
while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||
|
||||
WelcomeMessage welcome;
|
||||
MemWrite( &welcome.timerMul, m_timerMul );
|
||||
MemWrite( &welcome.initBegin, s_initTime.val );
|
||||
MemWrite( &welcome.initEnd, m_timeBegin.load( std::memory_order_relaxed ) );
|
||||
MemWrite( &welcome.delay, m_delay );
|
||||
MemWrite( &welcome.resolution, m_resolution );
|
||||
MemWrite( &welcome.epoch, m_epoch );
|
||||
welcome.timerMul = m_timerMul;
|
||||
welcome.initBegin = s_initTime.val;
|
||||
welcome.initEnd = m_timeBegin.load( std::memory_order_relaxed );
|
||||
welcome.delay = m_delay;
|
||||
welcome.resolution = m_resolution;
|
||||
welcome.epoch = m_epoch;
|
||||
memcpy( welcome.programName, procname, pnsz );
|
||||
memset( welcome.programName + pnsz, 0, WelcomeMessageProgramNameSize - pnsz );
|
||||
|
||||
@@ -251,7 +250,7 @@ void Profiler::Worker()
|
||||
}
|
||||
|
||||
QueueItem terminate;
|
||||
MemWrite( &terminate.hdr.type, QueueType::Terminate );
|
||||
terminate.hdr.type = QueueType::Terminate;
|
||||
if( !SendData( (const char*)&terminate, 1 ) ) return;
|
||||
for(;;)
|
||||
{
|
||||
@@ -289,23 +288,22 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token )
|
||||
while( item != end )
|
||||
{
|
||||
uint64_t ptr;
|
||||
const auto idx = MemRead<uint8_t>( &item->hdr.idx );
|
||||
if( idx < (int)QueueType::Terminate )
|
||||
if( item->hdr.idx < (int)QueueType::Terminate )
|
||||
{
|
||||
switch( (QueueType)idx )
|
||||
switch( item->hdr.type )
|
||||
{
|
||||
case QueueType::ZoneText:
|
||||
ptr = MemRead<uint64_t>( &item->zoneText.text );
|
||||
ptr = item->zoneText.text;
|
||||
SendString( ptr, (const char*)ptr, QueueType::CustomStringData );
|
||||
tracy_free( (void*)ptr );
|
||||
break;
|
||||
case QueueType::Message:
|
||||
ptr = MemRead<uint64_t>( &item->message.text );
|
||||
ptr = item->message.text;
|
||||
SendString( ptr, (const char*)ptr, QueueType::CustomStringData );
|
||||
tracy_free( (void*)ptr );
|
||||
break;
|
||||
case QueueType::ZoneBeginAllocSrcLoc:
|
||||
ptr = MemRead<uint64_t>( &item->zoneBegin.srcloc );
|
||||
ptr = item->zoneBegin.srcloc;
|
||||
SendSourceLocationPayload( ptr );
|
||||
tracy_free( (void*)ptr );
|
||||
break;
|
||||
@@ -314,7 +312,7 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !AppendData( item, QueueDataSize[idx] ) ) return ConnectionLost;
|
||||
if( !AppendData( item, QueueDataSize[item->hdr.idx] ) ) return ConnectionLost;
|
||||
item++;
|
||||
}
|
||||
}
|
||||
@@ -364,16 +362,16 @@ bool Profiler::SendString( uint64_t str, const char* ptr, QueueType type )
|
||||
assert( type == QueueType::StringData || type == QueueType::ThreadName || type == QueueType::CustomStringData || type == QueueType::PlotName );
|
||||
|
||||
QueueItem item;
|
||||
MemWrite( &item.hdr.type, type );
|
||||
MemWrite( &item.stringTransfer.ptr, str );
|
||||
item.hdr.type = type;
|
||||
item.stringTransfer.ptr = str;
|
||||
|
||||
auto len = strlen( ptr );
|
||||
assert( len <= std::numeric_limits<uint16_t>::max() );
|
||||
auto l16 = uint16_t( len );
|
||||
|
||||
NeedDataSize( QueueDataSize[(int)type] + sizeof( l16 ) + l16 );
|
||||
NeedDataSize( QueueDataSize[item.hdr.idx] + sizeof( l16 ) + l16 );
|
||||
|
||||
AppendData( &item, QueueDataSize[(int)type] );
|
||||
AppendData( &item, QueueDataSize[item.hdr.idx] );
|
||||
AppendData( &l16, sizeof( l16 ) );
|
||||
AppendData( ptr, l16 );
|
||||
|
||||
@@ -384,15 +382,15 @@ void Profiler::SendSourceLocation( uint64_t ptr )
|
||||
{
|
||||
auto srcloc = (const SourceLocation*)ptr;
|
||||
QueueItem item;
|
||||
MemWrite( &item.hdr.type, QueueType::SourceLocation );
|
||||
MemWrite( &item.srcloc.name, (uint64_t)srcloc->name );
|
||||
MemWrite( &item.srcloc.file, (uint64_t)srcloc->file );
|
||||
MemWrite( &item.srcloc.function, (uint64_t)srcloc->function );
|
||||
MemWrite( &item.srcloc.line, srcloc->line );
|
||||
MemWrite( &item.srcloc.r, uint8_t( ( srcloc->color ) & 0xFF ) );
|
||||
MemWrite( &item.srcloc.g, uint8_t( ( srcloc->color >> 8 ) & 0xFF ) );
|
||||
MemWrite( &item.srcloc.b, uint8_t( ( srcloc->color >> 16 ) & 0xFF ) );
|
||||
AppendData( &item, QueueDataSize[(int)QueueType::SourceLocation] );
|
||||
item.hdr.type = QueueType::SourceLocation;
|
||||
item.srcloc.name = (uint64_t)srcloc->name;
|
||||
item.srcloc.file = (uint64_t)srcloc->file;
|
||||
item.srcloc.function = (uint64_t)srcloc->function;
|
||||
item.srcloc.line = srcloc->line;
|
||||
item.srcloc.r = ( srcloc->color ) & 0xFF;
|
||||
item.srcloc.g = ( srcloc->color >> 8 ) & 0xFF;
|
||||
item.srcloc.b = ( srcloc->color >> 16 ) & 0xFF;
|
||||
AppendData( &item, QueueDataSize[item.hdr.idx] );
|
||||
}
|
||||
|
||||
bool Profiler::SendSourceLocationPayload( uint64_t _ptr )
|
||||
@@ -400,17 +398,17 @@ bool Profiler::SendSourceLocationPayload( uint64_t _ptr )
|
||||
auto ptr = (const char*)_ptr;
|
||||
|
||||
QueueItem item;
|
||||
MemWrite( &item.hdr.type, QueueType::SourceLocationPayload );
|
||||
MemWrite( &item.stringTransfer.ptr, _ptr );
|
||||
item.hdr.type = QueueType::SourceLocationPayload;
|
||||
item.stringTransfer.ptr = _ptr;
|
||||
|
||||
const auto len = *((uint32_t*)ptr);
|
||||
assert( len <= std::numeric_limits<uint16_t>::max() );
|
||||
assert( len > 4 );
|
||||
const auto l16 = uint16_t( len - 4 );
|
||||
|
||||
NeedDataSize( QueueDataSize[(int)QueueType::SourceLocationPayload] + sizeof( l16 ) + l16 );
|
||||
NeedDataSize( QueueDataSize[item.hdr.idx] + sizeof( l16 ) + l16 );
|
||||
|
||||
AppendData( &item, QueueDataSize[(int)QueueType::SourceLocationPayload] );
|
||||
AppendData( &item, QueueDataSize[item.hdr.idx] );
|
||||
AppendData( &l16, sizeof( l16 ) );
|
||||
AppendData( ptr + 4, l16 );
|
||||
|
||||
@@ -510,31 +508,19 @@ void Profiler::CalibrateDelay()
|
||||
Magic magic;
|
||||
auto& tail = ptoken->get_tail_index();
|
||||
auto item = ptoken->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneBegin );
|
||||
MemWrite( &item->zoneBegin.thread, GetThreadHandle() );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( item->zoneBegin.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneBegin.srcloc, (uint64_t)&__tracy_source_location );
|
||||
item->hdr.type = QueueType::ZoneBegin;
|
||||
item->zoneBegin.thread = GetThreadHandle();
|
||||
item->zoneBegin.time = GetTime( item->zoneBegin.cpu );
|
||||
item->zoneBegin.srcloc = (uint64_t)&__tracy_source_location;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
{
|
||||
Magic magic;
|
||||
auto& tail = ptoken->get_tail_index();
|
||||
auto item = ptoken->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneEnd );
|
||||
MemWrite( &item->zoneEnd.thread, uint64_t( 0 ) );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneEnd.time, GetTime( item->zoneEnd.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneEnd.time, GetTime( cpu ) );
|
||||
MemWrite( &item->zoneEnd.cpu, cpu );
|
||||
#endif
|
||||
item->hdr.type = QueueType::ZoneEnd;
|
||||
item->zoneEnd.thread = 0;
|
||||
item->zoneEnd.time = GetTime( item->zoneEnd.cpu );
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
@@ -552,31 +538,19 @@ void Profiler::CalibrateDelay()
|
||||
Magic magic;
|
||||
auto& tail = ptoken->get_tail_index();
|
||||
auto item = ptoken->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneBegin );
|
||||
MemWrite( &item->zoneBegin.thread, GetThreadHandle() );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( item->zoneBegin.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneBegin.srcloc, (uint64_t)&__tracy_source_location );
|
||||
item->hdr.type = QueueType::ZoneBegin;
|
||||
item->zoneBegin.thread = GetThreadHandle();
|
||||
item->zoneBegin.time = GetTime( item->zoneBegin.cpu );
|
||||
item->zoneBegin.srcloc = (uint64_t)&__tracy_source_location;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
{
|
||||
Magic magic;
|
||||
auto& tail = ptoken->get_tail_index();
|
||||
auto item = ptoken->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneEnd );
|
||||
MemWrite( &item->zoneEnd.thread, uint64_t( 0 ) );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneEnd.time, GetTime( item->zoneEnd.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneEnd.time, GetTime( cpu ) );
|
||||
MemWrite( &item->zoneEnd.cpu, cpu );
|
||||
#endif
|
||||
item->hdr.type = QueueType::ZoneEnd;
|
||||
item->zoneEnd.thread = 0;
|
||||
item->zoneEnd.time = GetTime( item->zoneEnd.cpu );
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "concurrentqueue.h"
|
||||
#include "../common/tracy_lz4.hpp"
|
||||
#include "../common/TracyQueue.hpp"
|
||||
#include "../common/TracyAlign.hpp"
|
||||
#include "../common/TracyAlloc.hpp"
|
||||
#include "../common/TracySystem.hpp"
|
||||
|
||||
@@ -110,8 +109,8 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::FrameMarkMsg );
|
||||
MemWrite( &item->frameMark.time, GetTime() );
|
||||
item->hdr.type = QueueType::FrameMarkMsg;
|
||||
item->frameMark.time = GetTime();
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -121,11 +120,11 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::PlotData );
|
||||
MemWrite( &item->plotData.name, (uint64_t)name );
|
||||
MemWrite( &item->plotData.time, GetTime() );
|
||||
MemWrite( &item->plotData.type, PlotDataType::Int );
|
||||
MemWrite( &item->plotData.data.i, val );
|
||||
item->hdr.type = QueueType::PlotData;
|
||||
item->plotData.name = (uint64_t)name;
|
||||
item->plotData.time = GetTime();
|
||||
item->plotData.type = PlotDataType::Int;
|
||||
item->plotData.data.i = val;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -135,11 +134,11 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::PlotData );
|
||||
MemWrite( &item->plotData.name, (uint64_t)name );
|
||||
MemWrite( &item->plotData.time, GetTime() );
|
||||
MemWrite( &item->plotData.type, PlotDataType::Float );
|
||||
MemWrite( &item->plotData.data.f, val );
|
||||
item->hdr.type = QueueType::PlotData;
|
||||
item->plotData.name = (uint64_t)name;
|
||||
item->plotData.time = GetTime();
|
||||
item->plotData.type = PlotDataType::Float;
|
||||
item->plotData.data.f = val;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -149,11 +148,11 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::PlotData );
|
||||
MemWrite( &item->plotData.name, (uint64_t)name );
|
||||
MemWrite( &item->plotData.time, GetTime() );
|
||||
MemWrite( &item->plotData.type, PlotDataType::Double );
|
||||
MemWrite( &item->plotData.data.d, val );
|
||||
item->hdr.type = QueueType::PlotData;
|
||||
item->plotData.name = (uint64_t)name;
|
||||
item->plotData.time = GetTime();
|
||||
item->plotData.type = PlotDataType::Double;
|
||||
item->plotData.data.d = val;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -166,10 +165,10 @@ public:
|
||||
ptr[size] = '\0';
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::Message );
|
||||
MemWrite( &item->message.time, GetTime() );
|
||||
MemWrite( &item->message.thread, GetThreadHandle() );
|
||||
MemWrite( &item->message.text, (uint64_t)ptr );
|
||||
item->hdr.type = QueueType::Message;
|
||||
item->message.time = GetTime();
|
||||
item->message.thread = GetThreadHandle();
|
||||
item->message.text = (uint64_t)ptr;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -179,10 +178,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::MessageLiteral );
|
||||
MemWrite( &item->message.time, GetTime() );
|
||||
MemWrite( &item->message.thread, GetThreadHandle() );
|
||||
MemWrite( &item->message.text, (uint64_t)txt );
|
||||
item->hdr.type = QueueType::MessageLiteral;
|
||||
item->message.time = GetTime();
|
||||
item->message.thread = GetThreadHandle();
|
||||
item->message.text = (uint64_t)txt;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/TracySystem.hpp"
|
||||
#include "../common/TracyAlign.hpp"
|
||||
#include "../common/TracyAlloc.hpp"
|
||||
#include "TracyProfiler.hpp"
|
||||
|
||||
@@ -23,16 +22,10 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneBegin );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( item->zoneBegin.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneBegin.thread, thread );
|
||||
MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );
|
||||
item->hdr.type = QueueType::ZoneBegin;
|
||||
item->zoneBegin.time = Profiler::GetTime( item->zoneBegin.cpu );
|
||||
item->zoneBegin.thread = thread;
|
||||
item->zoneBegin.srcloc = (uint64_t)srcloc;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -42,15 +35,9 @@ public:
|
||||
auto& token = s_token.ptr;
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneEnd );
|
||||
#ifdef TRACY_RDTSCP_SUPPORTED
|
||||
MemWrite( &item->zoneEnd.time, Profiler::GetTime( item->zoneEnd.cpu ) );
|
||||
#else
|
||||
uint32_t cpu;
|
||||
MemWrite( &item->zoneEnd.time, Profiler::GetTime( cpu ) );
|
||||
MemWrite( &item->zoneBegin.cpu, cpu );
|
||||
#endif
|
||||
MemWrite( &item->zoneEnd.thread, m_thread );
|
||||
item->hdr.type = QueueType::ZoneEnd;
|
||||
item->zoneEnd.time = Profiler::GetTime( item->zoneEnd.cpu );
|
||||
item->zoneEnd.thread = m_thread;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
@@ -63,9 +50,9 @@ public:
|
||||
ptr[size] = '\0';
|
||||
auto& tail = token->get_tail_index();
|
||||
auto item = token->enqueue_begin<moodycamel::CanAlloc>( magic );
|
||||
MemWrite( &item->hdr.type, QueueType::ZoneText );
|
||||
MemWrite( &item->zoneText.thread, m_thread );
|
||||
MemWrite( &item->zoneText.text, (uint64_t)ptr );
|
||||
item->hdr.type = QueueType::ZoneText;
|
||||
item->zoneText.thread = m_thread;
|
||||
item->zoneText.text = (uint64_t)ptr;
|
||||
tail.store( magic + 1, std::memory_order_release );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef __TRACYALIGN_HPP__
|
||||
#define __TRACYALIGN_HPP__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "TracyForceInline.hpp"
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
tracy_force_inline T MemRead( void* ptr )
|
||||
{
|
||||
T val;
|
||||
memcpy( &val, ptr, sizeof( T ) );
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
tracy_force_inline void MemWrite( void* ptr, T val )
|
||||
{
|
||||
memcpy( ptr, &val, sizeof( T ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,16 +27,18 @@ enum ServerQuery : uint8_t
|
||||
|
||||
enum { WelcomeMessageProgramNameSize = 64 };
|
||||
|
||||
#pragma pack( 1 )
|
||||
struct WelcomeMessage
|
||||
{
|
||||
double timerMul;
|
||||
int64_t initBegin;
|
||||
int64_t initEnd;
|
||||
uint64_t initBegin;
|
||||
uint64_t initEnd;
|
||||
uint64_t delay;
|
||||
uint64_t resolution;
|
||||
uint64_t epoch;
|
||||
char programName[WelcomeMessageProgramNameSize];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
enum { WelcomeMessageSize = sizeof( WelcomeMessage ) };
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ int Socket::Recv( void* _buf, int len, const timeval* tv )
|
||||
}
|
||||
}
|
||||
|
||||
bool Socket::Read( void* _buf, int len, const timeval* tv, std::function<bool()> exitCb )
|
||||
bool Socket::Read( void* _buf, int len, const timeval* tv, std::function< bool() > exitCb )
|
||||
{
|
||||
auto buf = (char*)_buf;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
int Send( const void* buf, int len );
|
||||
int Recv( void* buf, int len, const timeval* tv );
|
||||
|
||||
bool Read( void* buf, int len, const timeval* tv, std::function<bool()> exitCb );
|
||||
bool Read( void* buf, int len, const timeval* tv, std::function< bool() > exitCb );
|
||||
bool HasData();
|
||||
|
||||
Socket( const Socket& ) = delete;
|
||||
|
||||
@@ -84,7 +84,6 @@ void SetThreadName( std::thread::native_handle_type handle, const char* name )
|
||||
#endif
|
||||
#ifdef TRACY_COLLECT_THREAD_NAMES
|
||||
{
|
||||
rpmalloc_thread_initialize();
|
||||
const auto sz = strlen( name );
|
||||
char* buf = (char*)tracy_malloc( sz+1 );
|
||||
memcpy( buf, name, sz );
|
||||
@@ -113,7 +112,8 @@ const char* GetThreadName( uint64_t id )
|
||||
{
|
||||
if( ptr->id == id )
|
||||
{
|
||||
return ptr->name;
|
||||
strcpy( buf, ptr->name );
|
||||
return buf;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define __TRACYSYSTEM_HPP__
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
# if defined __ANDROID__ || defined __CYGWIN__ || defined __APPLE__ || defined _GNU_SOURCE
|
||||
# if defined __ANDROID__ || defined __CYGWIN__ || defined __APPLE__
|
||||
# define TRACY_COLLECT_THREAD_NAMES
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tracy_flat_hash_map.hpp"
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
namespace charutil
|
||||
@@ -48,11 +46,6 @@ struct Hasher
|
||||
}
|
||||
};
|
||||
|
||||
struct HasherPOT : public Hasher
|
||||
{
|
||||
typedef tracy::power_of_two_hash_policy hash_policy;
|
||||
};
|
||||
|
||||
struct Comparator
|
||||
{
|
||||
bool operator()( const char* lhs, const char* rhs ) const
|
||||
|
||||
@@ -79,14 +79,13 @@ struct ZoneEvent
|
||||
int32_t srcloc;
|
||||
int8_t cpu_start;
|
||||
int8_t cpu_end;
|
||||
StringIdx text;
|
||||
|
||||
// This must be last. All above is read/saved as-is.
|
||||
StringIdx text;
|
||||
Vector<ZoneEvent*> child;
|
||||
};
|
||||
|
||||
enum { ZoneEventSize = sizeof( ZoneEvent ) };
|
||||
static_assert( std::is_standard_layout<ZoneEvent>::value, "ZoneEvent is not standard layout" );
|
||||
|
||||
|
||||
struct LockEvent
|
||||
{
|
||||
@@ -130,12 +129,10 @@ struct GpuEvent
|
||||
int64_t gpuEnd;
|
||||
int32_t srcloc;
|
||||
|
||||
// This must be last. All above is read/saved as-is.
|
||||
Vector<GpuEvent*> child;
|
||||
};
|
||||
|
||||
enum { GpuEventSize = sizeof( GpuEvent ) };
|
||||
static_assert( std::is_standard_layout<GpuEvent>::value, "GpuEvent is not standard layout" );
|
||||
|
||||
#pragma pack()
|
||||
|
||||
@@ -177,7 +174,7 @@ struct LockMap
|
||||
{
|
||||
uint32_t srcloc;
|
||||
Vector<LockEvent*> timeline;
|
||||
flat_hash_map<uint64_t, uint8_t, nohash<uint64_t>> threadMap;
|
||||
std::unordered_map<uint64_t, uint8_t> threadMap;
|
||||
std::vector<uint64_t> threadList;
|
||||
LockType type;
|
||||
bool valid;
|
||||
|
||||
@@ -30,11 +30,30 @@ public:
|
||||
{
|
||||
if( size <= BufSize - m_offset )
|
||||
{
|
||||
ReadSmall( ptr, size );
|
||||
memcpy( ptr, m_buf[m_active] + m_offset, size );
|
||||
m_offset += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadBig( ptr, size );
|
||||
auto dst = (char*)ptr;
|
||||
while( size > 0 )
|
||||
{
|
||||
if( m_offset == BufSize )
|
||||
{
|
||||
m_active = 1 - m_active;
|
||||
m_offset = 0;
|
||||
uint32_t sz;
|
||||
fread( &sz, 1, sizeof( sz ), m_file );
|
||||
fread( m_lz4buf, 1, sz, m_file );
|
||||
LZ4_decompress_safe_continue( m_stream, m_lz4buf, m_buf[m_active], sz, BufSize );
|
||||
}
|
||||
|
||||
const auto sz = std::min( size, BufSize - m_offset );
|
||||
memcpy( dst, m_buf[m_active] + m_offset, sz );
|
||||
m_offset += sz;
|
||||
dst += sz;
|
||||
size -= sz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,42 +65,13 @@ private:
|
||||
, m_active( 1 )
|
||||
{}
|
||||
|
||||
tracy_force_inline void ReadSmall( void* ptr, size_t size )
|
||||
{
|
||||
memcpy( ptr, m_buf[m_active] + m_offset, size );
|
||||
m_offset += size;
|
||||
}
|
||||
|
||||
void ReadBig( void* ptr, size_t size )
|
||||
{
|
||||
char m_lz4buf[LZ4Size];
|
||||
auto dst = (char*)ptr;
|
||||
while( size > 0 )
|
||||
{
|
||||
if( m_offset == BufSize )
|
||||
{
|
||||
m_active = 1 - m_active;
|
||||
m_offset = 0;
|
||||
uint32_t sz;
|
||||
fread( &sz, 1, sizeof( sz ), m_file );
|
||||
fread( m_lz4buf, 1, sz, m_file );
|
||||
LZ4_decompress_safe_continue( m_stream, m_lz4buf, m_buf[m_active], sz, BufSize );
|
||||
}
|
||||
|
||||
const auto sz = std::min( size, BufSize - m_offset );
|
||||
memcpy( dst, m_buf[m_active] + m_offset, sz );
|
||||
m_offset += sz;
|
||||
dst += sz;
|
||||
size -= sz;
|
||||
}
|
||||
}
|
||||
|
||||
enum { BufSize = 64 * 1024 };
|
||||
enum { LZ4Size = LZ4_COMPRESSBOUND( BufSize ) };
|
||||
|
||||
LZ4_streamDecode_t* m_stream;
|
||||
FILE* m_file;
|
||||
char m_buf[2][BufSize];
|
||||
char m_lz4buf[LZ4Size];
|
||||
size_t m_offset;
|
||||
uint8_t m_active;
|
||||
};
|
||||
|
||||
@@ -34,11 +34,25 @@ public:
|
||||
{
|
||||
if( m_offset + size <= BufSize )
|
||||
{
|
||||
WriteSmall( ptr, size );
|
||||
memcpy( m_buf[m_active] + m_offset, ptr, size );
|
||||
m_offset += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteBig( ptr, size );
|
||||
auto src = (const char*)ptr;
|
||||
while( size > 0 )
|
||||
{
|
||||
const auto sz = std::min( size, BufSize - m_offset );
|
||||
memcpy( m_buf[m_active] + m_offset, src, sz );
|
||||
m_offset += sz;
|
||||
src += sz;
|
||||
size -= sz;
|
||||
|
||||
if( m_offset == BufSize )
|
||||
{
|
||||
WriteLz4Block();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,30 +64,6 @@ private:
|
||||
, m_active( 0 )
|
||||
{}
|
||||
|
||||
tracy_force_inline void WriteSmall( const void* ptr, size_t size )
|
||||
{
|
||||
memcpy( m_buf[m_active] + m_offset, ptr, size );
|
||||
m_offset += size;
|
||||
}
|
||||
|
||||
void WriteBig( const void* ptr, size_t size )
|
||||
{
|
||||
auto src = (const char*)ptr;
|
||||
while( size > 0 )
|
||||
{
|
||||
const auto sz = std::min( size, BufSize - m_offset );
|
||||
memcpy( m_buf[m_active] + m_offset, src, sz );
|
||||
m_offset += sz;
|
||||
src += sz;
|
||||
size -= sz;
|
||||
|
||||
if( m_offset == BufSize )
|
||||
{
|
||||
WriteLz4Block();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLz4Block()
|
||||
{
|
||||
char lz4[LZ4Size];
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
#if 0
|
||||
template<typename T>
|
||||
using Vector = std::vector<T>;
|
||||
#else
|
||||
#pragma pack( 1 )
|
||||
template<typename T>
|
||||
class Vector
|
||||
@@ -83,11 +87,6 @@ public:
|
||||
m_ptr[m_size++] = v;
|
||||
}
|
||||
|
||||
void push_back_no_space_check( const T& v )
|
||||
{
|
||||
m_ptr[m_size++] = v;
|
||||
}
|
||||
|
||||
void push_back( T&& v )
|
||||
{
|
||||
if( m_size == Capacity() ) AllocMore();
|
||||
@@ -166,11 +165,6 @@ public:
|
||||
void reserve( size_t cap )
|
||||
{
|
||||
if( cap == 0 || cap <= Capacity() ) return;
|
||||
reserve_non_zero( cap );
|
||||
}
|
||||
|
||||
void reserve_non_zero( size_t cap )
|
||||
{
|
||||
cap--;
|
||||
cap |= cap >> 1;
|
||||
cap |= cap >> 2;
|
||||
@@ -237,6 +231,7 @@ private:
|
||||
uint8_t m_capacity;
|
||||
};
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
1525
server/TracyView.cpp
1525
server/TracyView.cpp
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "TracyVector.hpp"
|
||||
@@ -73,7 +74,6 @@ private:
|
||||
void DrawOptions();
|
||||
void DrawMessages();
|
||||
void DrawFindZone();
|
||||
void DrawStatistics();
|
||||
|
||||
void DrawInfoWindow();
|
||||
void DrawZoneInfoWindow();
|
||||
@@ -96,34 +96,33 @@ private:
|
||||
void ZoneTooltip( const GpuEvent& ev );
|
||||
const ZoneEvent* GetZoneParent( const ZoneEvent& zone ) const;
|
||||
const GpuEvent* GetZoneParent( const GpuEvent& zone ) const;
|
||||
uint64_t GetZoneThread( const ZoneEvent& zone ) const;
|
||||
uint64_t GetZoneThread( const GpuEvent& zone ) const;
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
void FindZones();
|
||||
#endif
|
||||
void RecalcFindMatches();
|
||||
void RecalcFindMatches( const Vector<ZoneEvent*> &events, Vector<ZoneEvent*> &out, const int maxdepth = 0 );
|
||||
|
||||
flat_hash_map<const void*, bool, nohash<const void*>> m_visible;
|
||||
flat_hash_map<const void*, bool, nohash<const void*>> m_showFull;
|
||||
|
||||
tracy_force_inline bool& Visible( const void* ptr )
|
||||
template <typename T>
|
||||
bool& Visible( const T* ptr )
|
||||
{
|
||||
auto it = m_visible.find( ptr );
|
||||
if( it == m_visible.end() )
|
||||
static std::map <const T*, bool> visible;
|
||||
if( visible.find( ptr ) == visible.end() )
|
||||
{
|
||||
it = m_visible.emplace( ptr, true ).first;
|
||||
visible[ptr] = true;
|
||||
}
|
||||
return it->second;
|
||||
|
||||
return visible[ptr];
|
||||
}
|
||||
|
||||
tracy_force_inline bool& ShowFull( const void* ptr )
|
||||
template <typename T>
|
||||
bool& ShowFull( const T* ptr )
|
||||
{
|
||||
auto it = m_showFull.find( ptr );
|
||||
if( it == m_showFull.end() )
|
||||
static std::map <const T*, bool> showFull;
|
||||
if( showFull.find( ptr ) == showFull.end() )
|
||||
{
|
||||
it = m_showFull.emplace( ptr, true ).first;
|
||||
showFull[ptr] = true;
|
||||
}
|
||||
return it->second;
|
||||
|
||||
return showFull[ptr];
|
||||
}
|
||||
|
||||
Worker m_worker;
|
||||
@@ -158,48 +157,35 @@ private:
|
||||
|
||||
bool m_showOptions;
|
||||
bool m_showMessages;
|
||||
bool m_showStatistics;
|
||||
bool m_drawGpuZones;
|
||||
bool m_drawZones;
|
||||
bool m_drawLocks;
|
||||
bool m_drawPlots;
|
||||
bool m_onlyContendedLocks;
|
||||
int m_statSort;
|
||||
|
||||
Namespace m_namespace;
|
||||
Animation m_zoomAnim;
|
||||
|
||||
struct {
|
||||
enum : uint64_t { Unselected = std::numeric_limits<uint64_t>::max() - 1 };
|
||||
|
||||
bool show;
|
||||
std::vector<int32_t> match;
|
||||
std::map<uint64_t, Vector<ZoneEvent*>> threads;
|
||||
size_t processed;
|
||||
int selMatch = 0;
|
||||
uint64_t selThread = Unselected;
|
||||
std::vector<std::unique_ptr<ThreadData>> result;
|
||||
std::vector<uint32_t> counts;
|
||||
flat_hash_map<int32_t, bool> match;
|
||||
char pattern[1024] = { "" };
|
||||
int maxZonesPerThread = -1;
|
||||
int maxDepth = -1;
|
||||
bool logVal = false;
|
||||
bool logTime = false;
|
||||
bool cumulateTime = false;
|
||||
bool showThreads = true;
|
||||
bool sortByCounts = false;
|
||||
Region highlight;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ResetThreads();
|
||||
result.clear();
|
||||
match.clear();
|
||||
selMatch = 0;
|
||||
selThread = Unselected;
|
||||
counts.clear();
|
||||
highlight.active = false;
|
||||
}
|
||||
|
||||
void ResetThreads()
|
||||
{
|
||||
threads.clear();
|
||||
processed = 0;
|
||||
}
|
||||
} m_findZone;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
#include "TracyFileWrite.hpp"
|
||||
#include "TracyWorker.hpp"
|
||||
|
||||
#include "tracy_flat_hash_map.hpp"
|
||||
#include "tracy_pdqsort.h"
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
@@ -61,10 +58,15 @@ Worker::Worker( FileRead& f )
|
||||
}
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
m_data.frames.reserve_and_use( sz );
|
||||
f.Read( m_data.frames.data(), sizeof( uint64_t ) * sz );
|
||||
m_data.frames.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
uint64_t v;
|
||||
f.Read( &v, sizeof( v ) );
|
||||
m_data.frames.push_back( v );
|
||||
}
|
||||
|
||||
flat_hash_map<uint64_t, const char*, nohash<uint64_t>> pointerMap;
|
||||
std::unordered_map<uint64_t, const char*> pointerMap;
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
@@ -109,9 +111,13 @@ Worker::Worker( FileRead& f )
|
||||
}
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
m_data.sourceLocationExpand.reserve_and_use( sz );
|
||||
f.Read( m_data.sourceLocationExpand.data(), sizeof( uint64_t ) * sz );
|
||||
const auto sle = sz;
|
||||
m_data.sourceLocationExpand.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
uint64_t v;
|
||||
f.Read( &v, sizeof( v ) );
|
||||
m_data.sourceLocationExpand.push_back( v );
|
||||
}
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
m_data.sourceLocationPayload.reserve( sz );
|
||||
@@ -119,22 +125,10 @@ Worker::Worker( FileRead& f )
|
||||
{
|
||||
auto srcloc = m_slab.Alloc<SourceLocation>();
|
||||
f.Read( srcloc, sizeof( *srcloc ) );
|
||||
m_data.sourceLocationPayload.push_back_no_space_check( srcloc );
|
||||
m_data.sourceLocationPayload.push_back( srcloc );
|
||||
m_data.sourceLocationPayloadMap.emplace( srcloc, uint32_t( i ) );
|
||||
}
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
m_data.sourceLocationZones.reserve( sle + sz );
|
||||
for( uint64_t i=1; i<sle; i++ )
|
||||
{
|
||||
m_data.sourceLocationZones.emplace( int32_t( i ), SourceLocationZones() );
|
||||
}
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
m_data.sourceLocationZones.emplace( -int32_t( i + 1 ), SourceLocationZones() );
|
||||
}
|
||||
#endif
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
@@ -161,7 +155,7 @@ Worker::Worker( FileRead& f )
|
||||
{
|
||||
auto lev = m_slab.Alloc<LockEvent>();
|
||||
f.Read( lev, sizeof( LockEvent ) );
|
||||
lockmap.timeline.push_back_no_space_check( lev );
|
||||
lockmap.timeline.push_back( lev );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -170,13 +164,13 @@ Worker::Worker( FileRead& f )
|
||||
{
|
||||
auto lev = m_slab.Alloc<LockEventShared>();
|
||||
f.Read( lev, sizeof( LockEventShared ) );
|
||||
lockmap.timeline.push_back_no_space_check( lev );
|
||||
lockmap.timeline.push_back( lev );
|
||||
}
|
||||
}
|
||||
m_data.lockMap.emplace( id, std::move( lockmap ) );
|
||||
}
|
||||
|
||||
flat_hash_map<uint64_t, MessageData*, nohash<uint64_t>> msgMap;
|
||||
std::unordered_map<uint64_t, MessageData*> msgMap;
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
m_data.messages.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
@@ -185,7 +179,7 @@ Worker::Worker( FileRead& f )
|
||||
f.Read( &ptr, sizeof( ptr ) );
|
||||
auto msgdata = m_slab.Alloc<MessageData>();
|
||||
f.Read( msgdata, sizeof( *msgdata ) );
|
||||
m_data.messages.push_back_no_space_check( msgdata );
|
||||
m_data.messages.push_back( msgdata );
|
||||
msgMap.emplace( ptr, msgdata );
|
||||
}
|
||||
|
||||
@@ -196,7 +190,7 @@ Worker::Worker( FileRead& f )
|
||||
auto td = m_slab.AllocInit<ThreadData>();
|
||||
f.Read( &td->id, sizeof( td->id ) );
|
||||
f.Read( &td->count, sizeof( td->count ) );
|
||||
ReadTimeline( f, td->timeline, CompressThread( td->id ) );
|
||||
ReadTimeline( f, td->timeline );
|
||||
uint64_t msz;
|
||||
f.Read( &msz, sizeof( msz ) );
|
||||
td->messages.reserve( msz );
|
||||
@@ -204,19 +198,11 @@ Worker::Worker( FileRead& f )
|
||||
{
|
||||
uint64_t ptr;
|
||||
f.Read( &ptr, sizeof( ptr ) );
|
||||
td->messages.push_back_no_space_check( msgMap[ptr] );
|
||||
td->messages.push_back( msgMap[ptr] );
|
||||
}
|
||||
m_data.threads.push_back_no_space_check( td );
|
||||
m_data.threads.push_back( td );
|
||||
}
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
for( auto& v : m_data.sourceLocationZones )
|
||||
{
|
||||
auto& zones = v.second.zones;
|
||||
pdqsort_branchless( zones.begin(), zones.end(), []( const auto& lhs, const auto& rhs ) { return lhs.zone->start < rhs.zone->start; } );
|
||||
}
|
||||
#endif
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
m_data.gpuData.reserve( sz );
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
@@ -226,7 +212,7 @@ Worker::Worker( FileRead& f )
|
||||
f.Read( &ctx->accuracyBits, sizeof( ctx->accuracyBits ) );
|
||||
f.Read( &ctx->count, sizeof( ctx->count ) );
|
||||
ReadTimeline( f, ctx->timeline );
|
||||
m_data.gpuData.push_back_no_space_check( ctx );
|
||||
m_data.gpuData.push_back( ctx );
|
||||
}
|
||||
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
@@ -241,14 +227,14 @@ Worker::Worker( FileRead& f )
|
||||
f.Read( &psz, sizeof( psz ) );
|
||||
pd->data.reserve_and_use( psz );
|
||||
f.Read( pd->data.data(), psz * sizeof( PlotItem ) );
|
||||
m_data.plots.push_back_no_space_check( pd );
|
||||
m_data.plots.push_back( pd );
|
||||
}
|
||||
}
|
||||
|
||||
Worker::~Worker()
|
||||
{
|
||||
Shutdown();
|
||||
if( m_thread.joinable() )
|
||||
if ( m_thread.joinable() )
|
||||
{
|
||||
m_thread.join();
|
||||
}
|
||||
@@ -299,23 +285,23 @@ std::pair <int, int> Worker::GetFrameRange( int64_t from, int64_t to )
|
||||
return std::make_pair( zbegin, zend );
|
||||
}
|
||||
|
||||
int64_t Worker::GetZoneEnd( const ZoneEvent& ev )
|
||||
int64_t Worker::GetZoneEnd( const ZoneEvent& ev ) const
|
||||
{
|
||||
auto ptr = &ev;
|
||||
for(;;)
|
||||
{
|
||||
if( ptr->end >= 0 ) return ptr->end;
|
||||
if( ptr->end != -1 ) return ptr->end;
|
||||
if( ptr->child.empty() ) return ptr->start;
|
||||
ptr = ptr->child.back();
|
||||
}
|
||||
}
|
||||
|
||||
int64_t Worker::GetZoneEnd( const GpuEvent& ev )
|
||||
int64_t Worker::GetZoneEnd( const GpuEvent& ev ) const
|
||||
{
|
||||
auto ptr = &ev;
|
||||
for(;;)
|
||||
{
|
||||
if( ptr->gpuEnd >= 0 ) return ptr->gpuEnd;
|
||||
if( ptr->gpuEnd != -1 ) return ptr->gpuEnd;
|
||||
if( ptr->child.empty() ) return ptr->gpuStart;
|
||||
ptr = ptr->child.back();
|
||||
}
|
||||
@@ -418,36 +404,6 @@ std::vector<int32_t> Worker::GetMatchingSourceLocation( const char* query ) cons
|
||||
return match;
|
||||
}
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
const Worker::SourceLocationZones& Worker::GetZonesForSourceLocation( int32_t srcloc ) const
|
||||
{
|
||||
static const SourceLocationZones empty;
|
||||
auto it = m_data.sourceLocationZones.find( srcloc );
|
||||
return it != m_data.sourceLocationZones.end() ? it->second : empty;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t Worker::CompressThread( uint64_t thread )
|
||||
{
|
||||
auto it = m_data.threadMap.find( thread );
|
||||
if( it != m_data.threadMap.end() )
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CompressThreadNew( thread );
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Worker::CompressThreadNew( uint64_t thread )
|
||||
{
|
||||
auto sz = m_data.threadExpand.size();
|
||||
m_data.threadExpand.push_back( thread );
|
||||
m_data.threadMap.emplace( thread, sz );
|
||||
return sz;
|
||||
}
|
||||
|
||||
void Worker::Exec()
|
||||
{
|
||||
timeval tv;
|
||||
@@ -653,9 +609,6 @@ uint32_t Worker::NewShrinkedSourceLocation( uint64_t srcloc )
|
||||
{
|
||||
const auto sz = m_data.sourceLocationExpand.size();
|
||||
m_data.sourceLocationExpand.push_back( srcloc );
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
m_data.sourceLocationZones.emplace( sz, SourceLocationZones() );
|
||||
#endif
|
||||
m_sourceLocationShrink.emplace( srcloc, sz );
|
||||
return sz;
|
||||
}
|
||||
@@ -719,13 +672,6 @@ ThreadData* Worker::NewThread( uint64_t thread )
|
||||
void Worker::NewZone( ZoneEvent* zone, uint64_t thread )
|
||||
{
|
||||
m_data.zonesCnt++;
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
auto it = m_data.sourceLocationZones.find( zone->srcloc );
|
||||
assert( it != m_data.sourceLocationZones.end() );
|
||||
it->second.zones.push_back( ZoneThreadData { zone, CompressThread( thread ) } );
|
||||
#endif
|
||||
|
||||
auto td = NoticeThread( thread );
|
||||
td->count++;
|
||||
if( td->stack.empty() )
|
||||
@@ -990,9 +936,6 @@ void Worker::AddSourceLocationPayload( uint64_t ptr, char* data, size_t sz )
|
||||
m_data.sourceLocationPayloadMap.emplace( slptr, idx );
|
||||
m_pendingSourceLocationPayload.emplace( ptr, -int32_t( idx + 1 ) );
|
||||
m_data.sourceLocationPayload.push_back( slptr );
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
m_data.sourceLocationZones.emplace( -int32_t( idx + 1 ), SourceLocationZones() );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1114,8 +1057,7 @@ StringLocation Worker::StoreString( char* str, size_t sz )
|
||||
if( sit == m_data.stringMap.end() )
|
||||
{
|
||||
auto ptr = m_slab.Alloc<char>( sz+1 );
|
||||
memcpy( ptr, str, sz );
|
||||
ptr[sz] = '\0';
|
||||
memcpy( ptr, str, sz+1 );
|
||||
ret.ptr = ptr;
|
||||
ret.idx = m_data.stringData.size();
|
||||
m_data.stringMap.emplace( ptr, m_data.stringData.size() );
|
||||
@@ -1262,18 +1204,6 @@ void Worker::ProcessZoneEnd( const QueueZoneEnd& ev )
|
||||
assert( zone->end >= zone->start );
|
||||
|
||||
m_data.lastTime = std::max( m_data.lastTime, zone->end );
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
const auto timeSpan = zone->end - zone->start;
|
||||
if( timeSpan > 0 )
|
||||
{
|
||||
auto it = m_data.sourceLocationZones.find( zone->srcloc );
|
||||
assert( it != m_data.sourceLocationZones.end() );
|
||||
it->second.min = std::min( it->second.min, timeSpan );
|
||||
it->second.max = std::max( it->second.max, timeSpan );
|
||||
it->second.total += timeSpan;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Worker::ProcessFrameMark( const QueueFrameMark& ev )
|
||||
@@ -1625,13 +1555,26 @@ void Worker::ProcessGpuResync( const QueueGpuResync& ev )
|
||||
}
|
||||
}
|
||||
|
||||
void Worker::ReadTimeline( FileRead& f, Vector<ZoneEvent*>& vec, uint16_t thread )
|
||||
void Worker::ReadTimeline( FileRead& f, Vector<ZoneEvent*>& vec )
|
||||
{
|
||||
uint64_t sz;
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
if( sz != 0 )
|
||||
vec.reserve( sz );
|
||||
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
ReadTimeline( f, vec, thread, sz );
|
||||
auto zone = m_slab.AllocInit<ZoneEvent>();
|
||||
|
||||
m_data.zonesCnt++;
|
||||
vec.push_back( zone );
|
||||
|
||||
f.Read( &zone->start, sizeof( zone->start ) );
|
||||
f.Read( &zone->end, sizeof( zone->end ) );
|
||||
f.Read( &zone->srcloc, sizeof( zone->srcloc ) );
|
||||
f.Read( &zone->cpu_start, sizeof( zone->cpu_start ) );
|
||||
f.Read( &zone->cpu_end, sizeof( zone->cpu_end ) );
|
||||
f.Read( &zone->text, sizeof( zone->text ) );
|
||||
ReadTimeline( f, zone->child );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1639,57 +1582,19 @@ void Worker::ReadTimeline( FileRead& f, Vector<GpuEvent*>& vec )
|
||||
{
|
||||
uint64_t sz;
|
||||
f.Read( &sz, sizeof( sz ) );
|
||||
if( sz != 0 )
|
||||
{
|
||||
ReadTimeline( f, vec, sz );
|
||||
}
|
||||
}
|
||||
vec.reserve( sz );
|
||||
|
||||
void Worker::ReadTimeline( FileRead& f, Vector<ZoneEvent*>& vec, uint16_t thread, uint64_t size )
|
||||
{
|
||||
assert( size != 0 );
|
||||
vec.reserve_non_zero( size );
|
||||
m_data.zonesCnt += size;
|
||||
|
||||
for( uint64_t i=0; i<size; i++ )
|
||||
{
|
||||
auto zone = m_slab.Alloc<ZoneEvent>();
|
||||
vec.push_back_no_space_check( zone );
|
||||
new( &zone->child ) decltype( zone->child );
|
||||
|
||||
f.Read( zone, sizeof( ZoneEvent ) - sizeof( ZoneEvent::child ) );
|
||||
ReadTimeline( f, zone->child, thread );
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
auto it = m_data.sourceLocationZones.find( zone->srcloc );
|
||||
assert( it != m_data.sourceLocationZones.end() );
|
||||
it->second.zones.push_back( ZoneThreadData { zone, thread } );
|
||||
|
||||
if( zone->end >= 0 )
|
||||
{
|
||||
const auto timeSpan = zone->end - zone->start;
|
||||
if( timeSpan > 0 )
|
||||
{
|
||||
it->second.min = std::min( it->second.min, timeSpan );
|
||||
it->second.max = std::max( it->second.max, timeSpan );
|
||||
it->second.total += timeSpan;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Worker::ReadTimeline( FileRead& f, Vector<GpuEvent*>& vec, uint64_t size )
|
||||
{
|
||||
assert( size != 0 );
|
||||
vec.reserve_non_zero( size );
|
||||
|
||||
for( uint64_t i=0; i<size; i++ )
|
||||
for( uint64_t i=0; i<sz; i++ )
|
||||
{
|
||||
auto zone = m_slab.AllocInit<GpuEvent>();
|
||||
vec.push_back_no_space_check( zone );
|
||||
|
||||
f.Read( zone, sizeof( GpuEvent ) - sizeof( GpuEvent::child ) );
|
||||
vec.push_back( zone );
|
||||
|
||||
f.Read( &zone->cpuStart, sizeof( zone->cpuStart ) );
|
||||
f.Read( &zone->cpuEnd, sizeof( zone->cpuEnd ) );
|
||||
f.Read( &zone->gpuStart, sizeof( zone->gpuStart ) );
|
||||
f.Read( &zone->gpuEnd, sizeof( zone->gpuEnd ) );
|
||||
f.Read( &zone->srcloc, sizeof( zone->srcloc ) );
|
||||
ReadTimeline( f, zone->child );
|
||||
}
|
||||
}
|
||||
@@ -1847,7 +1752,12 @@ void Worker::WriteTimeline( FileWrite& f, const Vector<ZoneEvent*>& vec )
|
||||
|
||||
for( auto& v : vec )
|
||||
{
|
||||
f.Write( v, sizeof( ZoneEvent ) - sizeof( ZoneEvent::child ) );
|
||||
f.Write( &v->start, sizeof( v->start ) );
|
||||
f.Write( &v->end, sizeof( v->end ) );
|
||||
f.Write( &v->srcloc, sizeof( v->srcloc ) );
|
||||
f.Write( &v->cpu_start, sizeof( v->cpu_start ) );
|
||||
f.Write( &v->cpu_end, sizeof( v->cpu_end ) );
|
||||
f.Write( &v->text, sizeof( v->text ) );
|
||||
WriteTimeline( f, v->child );
|
||||
}
|
||||
}
|
||||
@@ -1859,7 +1769,11 @@ void Worker::WriteTimeline( FileWrite& f, const Vector<GpuEvent*>& vec )
|
||||
|
||||
for( auto& v : vec )
|
||||
{
|
||||
f.Write( v, sizeof( GpuEvent ) - sizeof( GpuEvent::child ) );
|
||||
f.Write( &v->cpuStart, sizeof( v->cpuStart ) );
|
||||
f.Write( &v->cpuEnd, sizeof( v->cpuEnd ) );
|
||||
f.Write( &v->gpuStart, sizeof( v->gpuStart ) );
|
||||
f.Write( &v->gpuEnd, sizeof( v->gpuEnd ) );
|
||||
f.Write( &v->srcloc, sizeof( v->srcloc ) );
|
||||
WriteTimeline( f, v->child );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#define __TRACYWORKER_HPP__
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "../common/tracy_lz4.hpp"
|
||||
@@ -23,30 +23,15 @@ namespace tracy
|
||||
class FileRead;
|
||||
class FileWrite;
|
||||
|
||||
template<typename T>
|
||||
struct nohash
|
||||
{
|
||||
size_t operator()( const T& v ) { return (size_t)v; }
|
||||
typedef tracy::power_of_two_hash_policy hash_policy;
|
||||
};
|
||||
|
||||
class Worker
|
||||
{
|
||||
#pragma pack( 1 )
|
||||
struct ZoneThreadData
|
||||
{
|
||||
ZoneEvent* zone;
|
||||
uint16_t thread;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct SourceLocationZones
|
||||
{
|
||||
SourceLocationZones()
|
||||
: min( std::numeric_limits<int64_t>::max() )
|
||||
, max( std::numeric_limits<int64_t>::min() )
|
||||
, total( 0 )
|
||||
{}
|
||||
|
||||
Vector<ZoneThreadData> zones;
|
||||
int64_t min;
|
||||
int64_t max;
|
||||
int64_t total;
|
||||
};
|
||||
|
||||
struct DataBlock
|
||||
{
|
||||
DataBlock() : zonesCnt( 0 ), lastTime( 0 ) {}
|
||||
@@ -62,21 +47,15 @@ class Worker
|
||||
|
||||
flat_hash_map<uint64_t, const char*, nohash<uint64_t>> strings;
|
||||
Vector<const char*> stringData;
|
||||
flat_hash_map<const char*, uint32_t, charutil::HasherPOT, charutil::Comparator> stringMap;
|
||||
std::unordered_map<const char*, uint32_t, charutil::Hasher, charutil::Comparator> stringMap;
|
||||
flat_hash_map<uint64_t, const char*, nohash<uint64_t>> threadNames;
|
||||
|
||||
flat_hash_map<uint64_t, SourceLocation, nohash<uint64_t>> sourceLocation;
|
||||
Vector<SourceLocation*> sourceLocationPayload;
|
||||
flat_hash_map<SourceLocation*, uint32_t, SourceLocationHasher, SourceLocationComparator> sourceLocationPayloadMap;
|
||||
Vector<uint64_t> sourceLocationExpand;
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
flat_hash_map<int32_t, SourceLocationZones, nohash<int32_t>> sourceLocationZones;
|
||||
#endif
|
||||
|
||||
std::map<uint32_t, LockMap> lockMap;
|
||||
|
||||
flat_hash_map<uint64_t, uint16_t, nohash<uint64_t>> threadMap;
|
||||
Vector<uint64_t> threadExpand;
|
||||
};
|
||||
|
||||
struct MbpsBlock
|
||||
@@ -114,15 +93,8 @@ public:
|
||||
const Vector<PlotData*>& GetPlots() const { return m_data.plots; }
|
||||
const Vector<ThreadData*>& GetThreadData() const { return m_data.threads; }
|
||||
|
||||
// Some zones may have incomplete timing data (only start time is available, end hasn't arrived yet).
|
||||
// GetZoneEnd() will try to infer the end time by looking at child zones (parent zone can't end
|
||||
// before its children have ended).
|
||||
// GetZoneEndDirect() will only return zone's direct timing data, without looking at children.
|
||||
static int64_t GetZoneEnd( const ZoneEvent& ev );
|
||||
static int64_t GetZoneEnd( const GpuEvent& ev );
|
||||
static tracy_force_inline int64_t GetZoneEndDirect( const ZoneEvent& ev ) { return ev.end >= 0 ? ev.end : ev.start; }
|
||||
static tracy_force_inline int64_t GetZoneEndDirect( const GpuEvent& ev ) { return ev.gpuEnd >= 0 ? ev.gpuEnd : ev.gpuStart; }
|
||||
|
||||
int64_t GetZoneEnd( const ZoneEvent& ev ) const;
|
||||
int64_t GetZoneEnd( const GpuEvent& ev ) const;
|
||||
const char* GetString( uint64_t ptr ) const;
|
||||
const char* GetString( const StringRef& ref ) const;
|
||||
const char* GetString( const StringIdx& idx ) const;
|
||||
@@ -131,21 +103,12 @@ public:
|
||||
|
||||
std::vector<int32_t> GetMatchingSourceLocation( const char* query ) const;
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
const SourceLocationZones& GetZonesForSourceLocation( int32_t srcloc ) const;
|
||||
const flat_hash_map<int32_t, SourceLocationZones, nohash<int32_t>>& GetSourceLocationZones() const { return m_data.sourceLocationZones; }
|
||||
#endif
|
||||
|
||||
tracy_force_inline uint16_t CompressThread( uint64_t thread );
|
||||
tracy_force_inline uint64_t DecompressThread( uint16_t thread ) const { assert( thread < m_data.threadExpand.size() ); return m_data.threadExpand[thread]; }
|
||||
|
||||
NonRecursiveBenaphore& GetMbpsDataLock() { return m_mbpsData.lock; }
|
||||
const std::vector<float>& GetMbpsData() const { return m_mbpsData.mbps; }
|
||||
float GetCompRatio() const { return m_mbpsData.compRatio; }
|
||||
|
||||
bool HasData() const { return m_hasData.load( std::memory_order_acquire ); }
|
||||
bool IsConnected() const { return m_connected.load( std::memory_order_relaxed ); }
|
||||
bool IsDataStatic() const { return !m_thread.joinable(); }
|
||||
void Shutdown() { m_shutdown.store( true, std::memory_order_relaxed ); }
|
||||
|
||||
void Write( FileWrite& f );
|
||||
@@ -207,13 +170,9 @@ private:
|
||||
void HandlePostponedPlots();
|
||||
|
||||
StringLocation StoreString( char* str, size_t sz );
|
||||
uint16_t CompressThreadNew( uint64_t thread );
|
||||
|
||||
tracy_force_inline void ReadTimeline( FileRead& f, Vector<ZoneEvent*>& vec, uint16_t thread );
|
||||
tracy_force_inline void ReadTimeline( FileRead& f, Vector<GpuEvent*>& vec );
|
||||
|
||||
void ReadTimeline( FileRead& f, Vector<ZoneEvent*>& vec, uint16_t thread, uint64_t size );
|
||||
void ReadTimeline( FileRead& f, Vector<GpuEvent*>& vec, uint64_t size );
|
||||
void ReadTimeline( FileRead& f, Vector<ZoneEvent*>& vec );
|
||||
void ReadTimeline( FileRead& f, Vector<GpuEvent*>& vec );
|
||||
|
||||
void WriteTimeline( FileWrite& f, const Vector<ZoneEvent*>& vec );
|
||||
void WriteTimeline( FileWrite& f, const Vector<GpuEvent*>& vec );
|
||||
@@ -242,7 +201,7 @@ private:
|
||||
flat_hash_map<uint64_t, StringLocation, nohash<uint64_t>> m_pendingCustomStrings;
|
||||
flat_hash_map<uint64_t, PlotData*, nohash<uint64_t>> m_pendingPlots;
|
||||
flat_hash_map<uint64_t, PlotData*, nohash<uint64_t>> m_plotMap;
|
||||
flat_hash_map<const char*, PlotData*, charutil::HasherPOT, charutil::Comparator> m_plotRev;
|
||||
std::unordered_map<const char*, PlotData*, charutil::Hasher, charutil::Comparator> m_plotRev;
|
||||
flat_hash_map<uint64_t, int32_t, nohash<uint64_t>> m_pendingSourceLocationPayload;
|
||||
Vector<uint64_t> m_sourceLocationQueue;
|
||||
flat_hash_map<uint64_t, uint32_t, nohash<uint64_t>> m_sourceLocationShrink;
|
||||
|
||||
@@ -26,13 +26,6 @@ namespace tracy
|
||||
struct prime_number_hash_policy;
|
||||
struct power_of_two_hash_policy;
|
||||
|
||||
template<typename T>
|
||||
struct nohash
|
||||
{
|
||||
size_t operator()( const T& v ) { return (size_t)v; }
|
||||
typedef tracy::power_of_two_hash_policy hash_policy;
|
||||
};
|
||||
|
||||
namespace detailv3
|
||||
{
|
||||
template<typename Result, typename Functor>
|
||||
|
||||
@@ -5,7 +5,7 @@ INCLUDES := $(shell pkg-config --cflags glfw3 gtk+-2.0) -I../../../imgui -I../..
|
||||
LIBS := $(shell pkg-config --libs glfw3 gtk+-2.0) -lpthread -ldl -lGL
|
||||
IMAGE := Tracy
|
||||
|
||||
FILTER := ../../../nfd/nfd_win.cpp
|
||||
FILTER := ../../../nfd/nfd_win.cpp ../../src/imgui_impl_dx11.cpp
|
||||
|
||||
BASE := $(shell egrep 'ClCompile.*cpp"' ../win32/$(IMAGE).vcxproj | sed -e 's/.*\"\(.*\)\".*/\1/' | sed -e 's@\\@/@g')
|
||||
BASE2 := $(shell egrep 'ClCompile.*c"' ../win32/$(IMAGE).vcxproj | sed -e 's/.*\"\(.*\)\".*/\1/' | sed -e 's@\\@/@g')
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;opengl32.lib;..\..\libs\glfw\lib-vc2015\glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -76,7 +76,7 @@
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>ws2_32.lib;opengl32.lib;..\..\libs\glfw\lib-vc2015\glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ws2_32.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -92,12 +92,18 @@
|
||||
<ClCompile Include="..\..\..\server\TracyMemory.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyView.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyWorker.cpp" />
|
||||
<ClCompile Include="..\..\libs\gl3w\GL\gl3w.c" />
|
||||
<ClCompile Include="..\..\src\imgui_impl_glfw_gl3.cpp" />
|
||||
<ClCompile Include="..\..\libs\gl3w\GL\gl3w.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\imgui_impl_dx11.cpp" />
|
||||
<ClCompile Include="..\..\src\imgui_impl_glfw_gl3.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\common\TracyAlign.hpp" />
|
||||
<ClInclude Include="..\..\..\common\TracyForceInline.hpp" />
|
||||
<ClInclude Include="..\..\..\common\TracyProtocol.hpp" />
|
||||
<ClInclude Include="..\..\..\common\TracyQueue.hpp" />
|
||||
@@ -128,9 +134,19 @@
|
||||
<ClInclude Include="..\..\..\server\tracy_flat_hash_map.hpp" />
|
||||
<ClInclude Include="..\..\..\server\tracy_pdqsort.h" />
|
||||
<ClInclude Include="..\..\..\server\tracy_sema.h" />
|
||||
<ClInclude Include="..\..\libs\gl3w\GL\gl3w.h" />
|
||||
<ClInclude Include="..\..\libs\gl3w\GL\glcorearb.h" />
|
||||
<ClInclude Include="..\..\src\imgui_impl_glfw_gl3.h" />
|
||||
<ClInclude Include="..\..\libs\gl3w\GL\gl3w.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\libs\gl3w\GL\glcorearb.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\imgui_impl_dx11.h" />
|
||||
<ClInclude Include="..\..\src\imgui_impl_glfw_gl3.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="DebugVis.natvis" />
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
<ClCompile Include="..\..\..\nfd\nfd_win.cpp">
|
||||
<Filter>nfd</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\imgui_impl_dx11.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
||||
@@ -164,8 +167,8 @@
|
||||
<ClInclude Include="..\..\..\server\TracyWorker.hpp">
|
||||
<Filter>server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\common\TracyAlign.hpp">
|
||||
<Filter>common</Filter>
|
||||
<ClInclude Include="..\..\src\imgui_impl_dx11.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
617
standalone/src/imgui_impl_dx11.cpp
Normal file
617
standalone/src/imgui_impl_dx11.cpp
Normal file
@@ -0,0 +1,617 @@
|
||||
// ImGui Win32 + DirectX11 binding
|
||||
// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_dx11.h"
|
||||
|
||||
// DirectX
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
|
||||
// Data
|
||||
static INT64 g_Time = 0;
|
||||
static INT64 g_TicksPerSecond = 0;
|
||||
|
||||
static HWND g_hWnd = 0;
|
||||
static ID3D11Device* g_pd3dDevice = NULL;
|
||||
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
||||
static ID3D11Buffer* g_pVB = NULL;
|
||||
static ID3D11Buffer* g_pIB = NULL;
|
||||
static ID3D10Blob * g_pVertexShaderBlob = NULL;
|
||||
static ID3D11VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D11InputLayout* g_pInputLayout = NULL;
|
||||
static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
|
||||
static ID3D10Blob * g_pPixelShaderBlob = NULL;
|
||||
static ID3D11PixelShader* g_pPixelShader = NULL;
|
||||
static ID3D11SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D11BlendState* g_pBlendState = NULL;
|
||||
static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
return;
|
||||
}
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
ctx->Unmap(g_pVB, 0);
|
||||
ctx->Unmap(g_pIB, 0);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
|
||||
float L = 0.0f;
|
||||
float R = ImGui::GetIO().DisplaySize.x;
|
||||
float B = ImGui::GetIO().DisplaySize.y;
|
||||
float T = 0.0f;
|
||||
float mvp[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
ctx->Unmap(g_pVertexConstantBuffer, 0);
|
||||
}
|
||||
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX11_STATE
|
||||
{
|
||||
UINT ScissorRectsCount, ViewportsCount;
|
||||
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||
ID3D11RasterizerState* RS;
|
||||
ID3D11BlendState* BlendState;
|
||||
FLOAT BlendFactor[4];
|
||||
UINT SampleMask;
|
||||
UINT StencilRef;
|
||||
ID3D11DepthStencilState* DepthStencilState;
|
||||
ID3D11ShaderResourceView* PSShaderResource;
|
||||
ID3D11SamplerState* PSSampler;
|
||||
ID3D11PixelShader* PS;
|
||||
ID3D11VertexShader* VS;
|
||||
UINT PSInstancesCount, VSInstancesCount;
|
||||
ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
|
||||
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
||||
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D11InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX11_STATE old;
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
ctx->RSGetState(&old.RS);
|
||||
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
old.PSInstancesCount = old.VSInstancesCount = 256;
|
||||
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
||||
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
ctx->IAGetInputLayout(&old.InputLayout);
|
||||
|
||||
// Setup viewport
|
||||
D3D11_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
||||
vp.Width = ImGui::GetIO().DisplaySize.x;
|
||||
vp.Height = ImGui::GetIO().DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0.0f;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(g_pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(g_pVertexShader, NULL, 0);
|
||||
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
ctx->PSSetShader(g_pPixelShader, NULL, 0);
|
||||
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
||||
ctx->RSSetState(g_pRasterizerState);
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
int idx_offset = 0;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
||||
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
|
||||
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
|
||||
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
static bool IsAnyMouseButtonDown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
|
||||
if (io.MouseDown[n])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process Win32 mouse/keyboard inputs.
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds.
|
||||
IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
switch (msg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
{
|
||||
int button = 0;
|
||||
if (msg == WM_LBUTTONDOWN) button = 0;
|
||||
if (msg == WM_RBUTTONDOWN) button = 1;
|
||||
if (msg == WM_MBUTTONDOWN) button = 2;
|
||||
if (!IsAnyMouseButtonDown() && GetCapture() == NULL)
|
||||
SetCapture(hwnd);
|
||||
io.MouseDown[button] = true;
|
||||
return 0;
|
||||
}
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
{
|
||||
int button = 0;
|
||||
if (msg == WM_LBUTTONUP) button = 0;
|
||||
if (msg == WM_RBUTTONUP) button = 1;
|
||||
if (msg == WM_MBUTTONUP) button = 2;
|
||||
io.MouseDown[button] = false;
|
||||
if (!IsAnyMouseButtonDown() && GetCapture() == hwnd)
|
||||
ReleaseCapture();
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSEWHEEL:
|
||||
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
|
||||
return 0;
|
||||
case WM_MOUSEMOVE:
|
||||
io.MousePos.x = (signed short)(lParam);
|
||||
io.MousePos.y = (signed short)(lParam >> 16);
|
||||
return 0;
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 1;
|
||||
return 0;
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 0;
|
||||
return 0;
|
||||
case WM_CHAR:
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
if (wParam > 0 && wParam < 0x10000)
|
||||
io.AddInputCharacter((unsigned short)wParam);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D11Texture2D *pTexture = NULL;
|
||||
D3D11_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
||||
pTexture->Release();
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)g_pFontTextureView;
|
||||
|
||||
// Create texture sampler
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
return false;
|
||||
if (g_pFontSampler)
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX11 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
static const char* vertexShader =
|
||||
"cbuffer vertexBuffer : register(b0) \
|
||||
{\
|
||||
float4x4 ProjectionMatrix; \
|
||||
};\
|
||||
struct VS_INPUT\
|
||||
{\
|
||||
float2 pos : POSITION;\
|
||||
float4 col : COLOR0;\
|
||||
float2 uv : TEXCOORD0;\
|
||||
};\
|
||||
\
|
||||
struct PS_INPUT\
|
||||
{\
|
||||
float4 pos : SV_POSITION;\
|
||||
float4 col : COLOR0;\
|
||||
float2 uv : TEXCOORD0;\
|
||||
};\
|
||||
\
|
||||
PS_INPUT main(VS_INPUT input)\
|
||||
{\
|
||||
PS_INPUT output;\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
|
||||
output.col = input.col;\
|
||||
output.uv = input.uv;\
|
||||
return output;\
|
||||
}";
|
||||
|
||||
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL);
|
||||
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)
|
||||
return false;
|
||||
|
||||
// Create the input layout
|
||||
D3D11_INPUT_ELEMENT_DESC local_layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
return false;
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the pixel shader
|
||||
{
|
||||
static const char* pixelShader =
|
||||
"struct PS_INPUT\
|
||||
{\
|
||||
float4 pos : SV_POSITION;\
|
||||
float4 col : COLOR0;\
|
||||
float2 uv : TEXCOORD0;\
|
||||
};\
|
||||
sampler sampler0;\
|
||||
Texture2D texture0;\
|
||||
\
|
||||
float4 main(PS_INPUT input) : SV_Target\
|
||||
{\
|
||||
float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
|
||||
return out_col; \
|
||||
}";
|
||||
|
||||
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL);
|
||||
if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the blending setup
|
||||
{
|
||||
D3D11_BLEND_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.AlphaToCoverageEnable = false;
|
||||
desc.RenderTarget[0].BlendEnable = true;
|
||||
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
{
|
||||
D3D11_RASTERIZER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.FillMode = D3D11_FILL_SOLID;
|
||||
desc.CullMode = D3D11_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.DepthEnable = false;
|
||||
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_CreateFontsTexture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
||||
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
||||
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
|
||||
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
|
||||
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context)
|
||||
{
|
||||
g_hWnd = (HWND)hwnd;
|
||||
g_pd3dDevice = device;
|
||||
g_pd3dDeviceContext = device_context;
|
||||
|
||||
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))
|
||||
return false;
|
||||
if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
|
||||
return false;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
|
||||
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
|
||||
io.KeyMap[ImGuiKey_Home] = VK_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = VK_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
|
||||
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
|
||||
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
io.KeyMap[ImGuiKey_X] = 'X';
|
||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
|
||||
io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||
io.ImeWindowHandle = g_hWnd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
ImGui::Shutdown();
|
||||
g_pd3dDevice = NULL;
|
||||
g_pd3dDeviceContext = NULL;
|
||||
g_hWnd = (HWND)0;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_NewFrame()
|
||||
{
|
||||
if (!g_pFontSampler)
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
RECT rect;
|
||||
GetClientRect(g_hWnd, &rect);
|
||||
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
||||
|
||||
// Setup time step
|
||||
INT64 current_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
|
||||
g_Time = current_time;
|
||||
|
||||
// Read keyboard modifiers inputs
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
io.KeySuper = false;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
|
||||
if (io.WantMoveMouse)
|
||||
{
|
||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||
ClientToScreen(g_hWnd, &pos);
|
||||
SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
if (io.MouseDrawCursor)
|
||||
SetCursor(NULL);
|
||||
|
||||
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
25
standalone/src/imgui_impl_dx11.h
Normal file
25
standalone/src/imgui_impl_dx11.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// ImGui Win32 + DirectX11 binding
|
||||
// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context);
|
||||
IMGUI_API void ImGui_ImplDX11_Shutdown();
|
||||
IMGUI_API void ImGui_ImplDX11_NewFrame();
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects();
|
||||
|
||||
// Handler for Win32 messages, update mouse/keyboard data.
|
||||
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
|
||||
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
|
||||
/*
|
||||
IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
*/
|
||||
@@ -1,33 +1,155 @@
|
||||
#ifdef _MSC_VER
|
||||
# define TRACY_DIRECTX
|
||||
#endif
|
||||
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_glfw_gl3.h"
|
||||
#include <stdio.h>
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <memory>
|
||||
#include "../nfd/nfd.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef TRACY_DIRECTX
|
||||
# include "imgui_impl_dx11.h"
|
||||
# include <d3d11.h>
|
||||
# define DIRECTINPUT_VERSION 0x0800
|
||||
# include <dinput.h>
|
||||
# include <tchar.h>
|
||||
#else
|
||||
# include "imgui_impl_glfw_gl3.h"
|
||||
# include <GL/gl3w.h>
|
||||
# include <GLFW/glfw3.h>
|
||||
#endif
|
||||
|
||||
#include "../../server/TracyFileRead.hpp"
|
||||
#include "../../server/TracyView.hpp"
|
||||
|
||||
#ifdef TRACY_DIRECTX
|
||||
// Data
|
||||
static ID3D11Device* g_pd3dDevice = NULL;
|
||||
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
||||
static IDXGISwapChain* g_pSwapChain = NULL;
|
||||
static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
|
||||
|
||||
void CreateRenderTarget()
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
g_pSwapChain->GetDesc(&sd);
|
||||
|
||||
// Create the render target
|
||||
ID3D11Texture2D* pBackBuffer;
|
||||
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
||||
ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));
|
||||
render_target_view_desc.Format = sd.BufferDesc.Format;
|
||||
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView);
|
||||
pBackBuffer->Release();
|
||||
}
|
||||
|
||||
void CleanupRenderTarget()
|
||||
{
|
||||
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
|
||||
}
|
||||
|
||||
HRESULT CreateDeviceD3D(HWND hWnd)
|
||||
{
|
||||
// Setup swap chain
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
{
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
sd.BufferCount = 2;
|
||||
sd.BufferDesc.Width = 0;
|
||||
sd.BufferDesc.Height = 0;
|
||||
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.OutputWindow = hWnd;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = 0;
|
||||
sd.Windowed = TRUE;
|
||||
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
}
|
||||
|
||||
UINT createDeviceFlags = 0;
|
||||
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
|
||||
if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
CreateRenderTarget();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CleanupDeviceD3D()
|
||||
{
|
||||
CleanupRenderTarget();
|
||||
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
|
||||
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
}
|
||||
|
||||
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
return true;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_SIZE:
|
||||
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
|
||||
{
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
CleanupRenderTarget();
|
||||
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
|
||||
CreateRenderTarget();
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSCOMMAND:
|
||||
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
|
||||
return 0;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
#else
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error %d: %s\n", error, description);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main( int argc, char** argv )
|
||||
int main(int, char**)
|
||||
{
|
||||
std::unique_ptr<tracy::View> view;
|
||||
#ifdef TRACY_DIRECTX
|
||||
// Create application window
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("TracyServer"), NULL };
|
||||
RegisterClassEx(&wc);
|
||||
HWND hwnd = CreateWindow(_T("TracyServer"), _T("Tracy server"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1650, 960, NULL, NULL, wc.hInstance, NULL);
|
||||
|
||||
if( argc == 2 )
|
||||
// Initialize Direct3D
|
||||
if (CreateDeviceD3D(hwnd) < 0)
|
||||
{
|
||||
auto f = std::unique_ptr<tracy::FileRead>( tracy::FileRead::Open( argv[1] ) );
|
||||
if( f )
|
||||
{
|
||||
view = std::make_unique<tracy::View>( *f );
|
||||
}
|
||||
CleanupDeviceD3D();
|
||||
UnregisterClass(_T("TracyServer"), wc.hInstance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Show the window
|
||||
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext);
|
||||
#else
|
||||
// Setup window
|
||||
glfwSetErrorCallback(error_callback);
|
||||
if (!glfwInit())
|
||||
@@ -45,6 +167,7 @@ int main( int argc, char** argv )
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplGlfwGL3_Init(window, true);
|
||||
#endif
|
||||
|
||||
// Load Fonts
|
||||
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details)
|
||||
@@ -76,12 +199,31 @@ int main( int argc, char** argv )
|
||||
ImVec4 clear_color = ImColor(114, 144, 154);
|
||||
|
||||
char addr[1024] = { "127.0.0.1" };
|
||||
std::unique_ptr<tracy::View> view;
|
||||
|
||||
#ifdef TRACY_DIRECTX
|
||||
MSG msg;
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
while (msg.message != WM_QUIT)
|
||||
{
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
continue;
|
||||
}
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
#else
|
||||
// Main loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
glfwPollEvents();
|
||||
ImGui_ImplGlfwGL3_NewFrame();
|
||||
#endif
|
||||
|
||||
if( !view )
|
||||
{
|
||||
@@ -112,6 +254,20 @@ int main( int argc, char** argv )
|
||||
view->Draw();
|
||||
}
|
||||
|
||||
#ifdef TRACY_DIRECTX
|
||||
// Rendering
|
||||
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
|
||||
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color);
|
||||
ImGui::Render();
|
||||
|
||||
g_pSwapChain->Present(1, 0); // Present with vsync
|
||||
//g_pSwapChain->Present(0, 0); // Present without vsync
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
CleanupDeviceD3D();
|
||||
UnregisterClass(_T("TracyServer"), wc.hInstance);
|
||||
#else
|
||||
// Rendering
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
@@ -125,6 +281,7 @@ int main( int argc, char** argv )
|
||||
// Cleanup
|
||||
ImGui_ImplGlfwGL3_Shutdown();
|
||||
glfwTerminate();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user