Compare commits

..

2 Commits
v0.2 ... dx11

Author SHA1 Message Date
Bartosz Taudul
5ea4a326f3 Filter-out DirectX 11 sources on unix. 2018-03-15 21:04:04 +01:00
Bartosz Taudul
62957310a0 Use DirectX 11 for Windows version of standalone server. 2018-03-15 21:04:04 +01:00
35 changed files with 1716 additions and 1769 deletions

77
FAQ.md
View File

@@ -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
View File

@@ -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.

View File

@@ -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
![](doc/design.svg)
@@ -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).

View File

@@ -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;
}

View File

@@ -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 );
}
};

View File

@@ -1,6 +1,6 @@
CFLAGS +=
CXXFLAGS := $(CFLAGS) -std=gnu++14
DEFINES += -DTRACY_NO_STATISTICS
DEFINES +=
INCLUDES :=
LIBS := -lpthread
IMAGE := capture

View File

@@ -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" />

View File

@@ -95,8 +95,5 @@
<ClInclude Include="..\..\src\getopt.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\TracyAlign.hpp">
<Filter>common</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -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 );

View File

@@ -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 );
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}

View File

@@ -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 );
}

View File

@@ -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

View File

@@ -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 ) };

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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];

View File

@@ -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
}

File diff suppressed because it is too large Load Diff

View File

@@ -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;
};

View File

@@ -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 );
}
}

View File

@@ -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;

View File

@@ -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>

View File

@@ -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')

View File

@@ -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" />

View File

@@ -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>

View 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 *)&current_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();
}

View 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);
*/

View File

@@ -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;
}