mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Send capture progress over an active target control connection
This commit is contained in:
@@ -1113,6 +1113,12 @@ void LiveCapture::connectionThreadEntry()
|
||||
});
|
||||
}
|
||||
|
||||
if(msg.type == TargetControlMessageType::CaptureProgress)
|
||||
{
|
||||
float progress = msg.capProgress;
|
||||
GUIInvoke::call([this, progress]() {});
|
||||
}
|
||||
|
||||
if(msg.type == TargetControlMessageType::NewCapture)
|
||||
{
|
||||
uint32_t capID = msg.newCapture.captureId;
|
||||
|
||||
@@ -476,6 +476,12 @@ struct TargetControlMessage
|
||||
BusyData busy;
|
||||
DOCUMENT("The :class:`new child process data <NewChildData>`.");
|
||||
NewChildData newChild;
|
||||
DOCUMENT(R"(The progress of an on-going capture.
|
||||
|
||||
When valid, will be in the range of 0.0 to 1.0 (0 - 100%). If not valid when a capture isn't going
|
||||
or has finished, it will be -1.0
|
||||
)");
|
||||
float capProgress = -1.0f;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(TargetControlMessage);
|
||||
|
||||
@@ -2929,6 +2929,10 @@ DOCUMENT(R"(The type of message received from or sent to an application target c
|
||||
.. data:: NewChild
|
||||
|
||||
The target has created a child process.
|
||||
|
||||
.. data:: CaptureProgress
|
||||
|
||||
Progress update on an on-going frame capture.
|
||||
)");
|
||||
enum class TargetControlMessageType : uint32_t
|
||||
{
|
||||
@@ -2940,6 +2944,7 @@ enum class TargetControlMessageType : uint32_t
|
||||
CaptureCopied,
|
||||
RegisterAPI,
|
||||
NewChild,
|
||||
CaptureProgress,
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_ENUM(TargetControlMessageType);
|
||||
|
||||
+42
-9
@@ -247,8 +247,14 @@ enum class CaptureProgress
|
||||
{
|
||||
PrepareInitialStates,
|
||||
First = PrepareInitialStates,
|
||||
// frame capture goes here but we have no way to estimate its length, and the progress would be
|
||||
// updated all over the place as every API call or every draw call would have to update it.
|
||||
// In general we can't know how long the frame capture will take to have an explicit progress, but
|
||||
// we can hack it by getting closer and closer to 100% without quite reaching it, with some
|
||||
// heuristic for how far we expect to get. Some APIs will have no useful way to update progress
|
||||
// during frame capture, but for explicit APIs like Vulkan we can update once per submission, and
|
||||
// tune it so that it doesn't start crawling approaching 100% until well past the number of
|
||||
// submissions we'd expect in a frame.
|
||||
// Other APIs will simply skip this progress section entirely, which is fine.
|
||||
FrameCapture,
|
||||
AddReferencedResources,
|
||||
SerialiseInitialStates,
|
||||
SerialiseFrameContents,
|
||||
@@ -259,18 +265,45 @@ enum class CaptureProgress
|
||||
DECLARE_REFLECTION_ENUM(CaptureProgress);
|
||||
ITERABLE_OPERATORS(CaptureProgress);
|
||||
|
||||
// different APIs spend their capture time in different places. So the weighting is roughly even for
|
||||
// the potential hot-spots. So D3D11 might zoom past the PrepareInitialStates while Vulkan takes a
|
||||
// couple of seconds, but then the situation is reversed for AddReferencedResources
|
||||
inline constexpr float ProgressWeight(CaptureProgress section)
|
||||
{
|
||||
// values must sum to 1.0
|
||||
return section == CaptureProgress::PrepareInitialStates
|
||||
? 0.35f
|
||||
? 0.25f
|
||||
: section == CaptureProgress::AddReferencedResources
|
||||
? 0.1f
|
||||
: section == CaptureProgress::SerialiseInitialStates
|
||||
? 0.5f
|
||||
: section == CaptureProgress::SerialiseFrameContents
|
||||
? 0.04f
|
||||
: section == CaptureProgress::FileWriting ? 0.01f : 0.0f;
|
||||
? 0.25f
|
||||
: section == CaptureProgress::FrameCapture
|
||||
? 0.15f
|
||||
: section == CaptureProgress::SerialiseInitialStates
|
||||
? 0.25f
|
||||
: section == CaptureProgress::SerialiseFrameContents
|
||||
? 0.08f
|
||||
: section == CaptureProgress::FileWriting ? 0.02f : 0.0f;
|
||||
}
|
||||
|
||||
// utility function to fake progress with x going from 0 to infinity, mapping to 0% to 100% in an
|
||||
// inverse curve. For x from 0 to maxX the progress is reasonably spaced, past that it will be quite
|
||||
// crushed.
|
||||
//
|
||||
// The equation is y = 1 - (1 / (x * param) + 1)
|
||||
//
|
||||
// => maxX will be when the curve reaches 80%
|
||||
// 0.8 = 1 - (1 / (maxX * param) + 1)
|
||||
//
|
||||
// => gather constants on RHS
|
||||
// 1 / (maxX * param) + 1 = 0.2
|
||||
//
|
||||
// => switch denominators
|
||||
// maxX * param + 1 = 5
|
||||
//
|
||||
// => re-arrange for param
|
||||
// param = 4 / maxX
|
||||
inline constexpr float FakeProgress(uint32_t x, uint32_t maxX)
|
||||
{
|
||||
return 1.0f - (1.0f / (x * (4.0f / float(maxX)) + 1));
|
||||
}
|
||||
|
||||
class IRemoteDriver;
|
||||
|
||||
@@ -44,6 +44,7 @@ enum PacketType : uint32_t
|
||||
ePacket_DeleteCapture,
|
||||
ePacket_QueueCapture,
|
||||
ePacket_NewChild,
|
||||
ePacket_CaptureProgress,
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_ENUM(PacketType);
|
||||
@@ -104,13 +105,18 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
|
||||
return;
|
||||
}
|
||||
|
||||
const int pingtime = 1000; // ping every 1000ms
|
||||
const int ticktime = 10; // tick every 10ms
|
||||
float captureProgress = -1.0f;
|
||||
RenderDoc::Inst().SetProgressPointer<CaptureProgress>(&captureProgress);
|
||||
|
||||
const int pingtime = 1000; // ping every 1000ms
|
||||
const int ticktime = 10; // tick every 10ms
|
||||
const int progresstime = 100; // update capture progress every 100ms
|
||||
int curtime = 0;
|
||||
|
||||
std::vector<CaptureData> captures;
|
||||
std::vector<pair<uint32_t, uint32_t> > children;
|
||||
std::map<RDCDriver, bool> drivers;
|
||||
float prevCaptureProgress = captureProgress;
|
||||
|
||||
while(client)
|
||||
{
|
||||
@@ -200,6 +206,26 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
|
||||
SERIALISE_ELEMENT(children.back().second);
|
||||
}
|
||||
}
|
||||
else if(prevCaptureProgress != captureProgress)
|
||||
{
|
||||
if(captureProgress == 1.0f || captureProgress == -1.0f)
|
||||
captureProgress = -1.0f;
|
||||
|
||||
// send progress packets at reduced rate (not every tick), or if the progress is finished.
|
||||
// we don't need to ping while we're sending capture progress, so we re-use curtime
|
||||
if(captureProgress == -1.0f || curtime > progresstime)
|
||||
{
|
||||
curtime = 0;
|
||||
|
||||
prevCaptureProgress = captureProgress;
|
||||
|
||||
WRITE_DATA_SCOPE();
|
||||
{
|
||||
SCOPED_SERIALISE_CHUNK(ePacket_CaptureProgress);
|
||||
SERIALISE_ELEMENT(captureProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(curtime > pingtime)
|
||||
{
|
||||
@@ -284,6 +310,8 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
|
||||
}
|
||||
}
|
||||
|
||||
RenderDoc::Inst().SetProgressPointer<CaptureProgress>(NULL);
|
||||
|
||||
// give up our connection
|
||||
{
|
||||
SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock);
|
||||
@@ -610,6 +638,16 @@ public:
|
||||
reader.EndChunk();
|
||||
return msg;
|
||||
}
|
||||
else if(type == ePacket_CaptureProgress)
|
||||
{
|
||||
msg.type = TargetControlMessageType::CaptureProgress;
|
||||
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(msg.capProgress).Named("Capture Progress");
|
||||
|
||||
reader.EndChunk();
|
||||
return msg;
|
||||
}
|
||||
else if(type == ePacket_NewCapture)
|
||||
{
|
||||
msg.type = TargetControlMessageType::NewCapture;
|
||||
|
||||
@@ -333,6 +333,9 @@ void STDMETHODCALLTYPE WrappedID3D12CommandQueue::ExecuteCommandLists(
|
||||
RenderDoc::Inst().AddActiveDriver(RDCDriver::Vulkan, false);
|
||||
}
|
||||
|
||||
if(IsActiveCapturing(m_State))
|
||||
m_pDevice->AddCaptureSubmission();
|
||||
|
||||
SERIALISE_TIME_CALL(m_pReal->ExecuteCommandLists(NumCommandLists, unwrapped));
|
||||
|
||||
if(IsCaptureMode(m_State))
|
||||
|
||||
@@ -540,6 +540,18 @@ void WrappedID3D12Device::ApplyInitialContents()
|
||||
initStateCurList = NULL;
|
||||
}
|
||||
|
||||
void WrappedID3D12Device::AddCaptureSubmission()
|
||||
{
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
// 15 is quite a lot of submissions.
|
||||
const int expectedMaxSubmissions = 15;
|
||||
|
||||
RenderDoc::Inst().SetProgress(CaptureProgress::FrameCapture, FakeProgress(m_SubmitCounter, 15));
|
||||
m_SubmitCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
void WrappedID3D12Device::CheckForDeath()
|
||||
{
|
||||
if(!m_Alive)
|
||||
@@ -1227,6 +1239,8 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
m_AppControlledCapture = true;
|
||||
|
||||
m_SubmitCounter = 0;
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
|
||||
@@ -299,6 +299,8 @@ private:
|
||||
Threading::CriticalSection m_CapTransitionLock;
|
||||
CaptureState m_State;
|
||||
|
||||
uint32_t m_SubmitCounter = 0;
|
||||
|
||||
D3D12InitParams m_InitParams;
|
||||
uint64_t m_SectionVersion;
|
||||
ID3D12InfoQueue *m_pInfoQueue;
|
||||
@@ -458,6 +460,8 @@ public:
|
||||
ID3D12Resource *GetUploadBuffer(uint64_t chunkOffset, uint64_t byteSize);
|
||||
void ApplyInitialContents();
|
||||
|
||||
void AddCaptureSubmission();
|
||||
|
||||
void ExecuteList(ID3D12GraphicsCommandList *list, ID3D12CommandQueue *queue = NULL);
|
||||
void ExecuteLists(ID3D12CommandQueue *queue = NULL);
|
||||
void FlushLists(bool forceSync = false, ID3D12CommandQueue *queue = NULL);
|
||||
|
||||
@@ -881,6 +881,8 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
m_AppControlledCapture = true;
|
||||
|
||||
m_SubmitCounter = 0;
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
|
||||
@@ -221,6 +221,7 @@ private:
|
||||
bool m_AppControlledCapture;
|
||||
|
||||
bool m_MarkedActive = false;
|
||||
uint32_t m_SubmitCounter = 0;
|
||||
|
||||
uint64_t threadSerialiserTLSSlot;
|
||||
|
||||
|
||||
@@ -416,6 +416,15 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
|
||||
RenderDoc::Inst().AddActiveDriver(RDCDriver::Vulkan, false);
|
||||
}
|
||||
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
// 15 is quite a lot of submissions.
|
||||
const int expectedMaxSubmissions = 15;
|
||||
|
||||
RenderDoc::Inst().SetProgress(CaptureProgress::FrameCapture, FakeProgress(m_SubmitCounter, 15));
|
||||
m_SubmitCounter++;
|
||||
}
|
||||
|
||||
size_t tempmemSize = sizeof(VkSubmitInfo) * submitCount;
|
||||
|
||||
// need to count how many semaphore and command buffer arrays to allocate for
|
||||
|
||||
Reference in New Issue
Block a user