mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-26 08:26:50 +00:00
Allow queuing a sequence of frames both before capture, or while running
* We also make the frame counting consistent: Frame 0 is the frame from device initialisation to first present, Frame 1 is from first present to second, and so on after that.
This commit is contained in:
@@ -1108,11 +1108,11 @@ void CaptureDialog::TriggerCapture()
|
||||
QString name = m_ProcessModel->data(m_ProcessModel->index(item.row(), 0)).toString();
|
||||
uint32_t PID = m_ProcessModel->data(m_ProcessModel->index(item.row(), 1)).toUInt();
|
||||
|
||||
m_InjectCallback(PID, Settings().environment, name, Settings().options,
|
||||
[this](LiveCapture *live) {
|
||||
if(ui->queueFrameCap->isChecked())
|
||||
live->QueueCapture((int)ui->queuedFrame->value());
|
||||
});
|
||||
m_InjectCallback(
|
||||
PID, Settings().environment, name, Settings().options, [this](LiveCapture *live) {
|
||||
if(ui->queueFrameCap->isChecked())
|
||||
live->QueueCapture((int)ui->queuedFrame->value(), (int)ui->numFrames->value());
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1148,7 +1148,8 @@ void CaptureDialog::TriggerCapture()
|
||||
m_CaptureCallback(exe, workingDir, cmdLine, Settings().environment, Settings().options,
|
||||
[this](LiveCapture *live) {
|
||||
if(ui->queueFrameCap->isChecked())
|
||||
live->QueueCapture((int)ui->queuedFrame->value());
|
||||
live->QueueCapture((int)ui->queuedFrame->value(),
|
||||
(int)ui->numFrames->value());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,6 +587,38 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="numFramesLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string># Frames:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="numFrames">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="ActionsSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -185,9 +185,10 @@ LiveCapture::~LiveCapture()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LiveCapture::QueueCapture(int frameNumber)
|
||||
void LiveCapture::QueueCapture(int frameNumber, int numFrames)
|
||||
{
|
||||
m_CaptureFrameNum = frameNumber;
|
||||
m_QueueCaptureFrameNum = frameNumber;
|
||||
m_CaptureNumFrames = numFrames;
|
||||
m_QueueCapture = true;
|
||||
}
|
||||
|
||||
@@ -275,13 +276,13 @@ void LiveCapture::on_childProcesses_itemActivated(QListWidgetItem *item)
|
||||
|
||||
void LiveCapture::on_queueCap_clicked()
|
||||
{
|
||||
m_CaptureFrameNum = (int)ui->captureFrame->value();
|
||||
m_CaptureNumFrames = (int)ui->numFrames->value();
|
||||
m_QueueCaptureFrameNum = (int)ui->captureFrame->value();
|
||||
m_QueueCapture = true;
|
||||
}
|
||||
|
||||
void LiveCapture::on_triggerCapture_clicked()
|
||||
{
|
||||
m_CaptureNumFrames = (int)ui->numFrames->value();
|
||||
if(ui->captureDelay->value() == 0.0)
|
||||
{
|
||||
m_TriggerCapture = true;
|
||||
@@ -482,8 +483,9 @@ void LiveCapture::captureCountdownTick()
|
||||
if(m_CaptureCounter == 0)
|
||||
{
|
||||
m_TriggerCapture = true;
|
||||
m_CaptureNumFrames = (int)ui->numFrames->value();
|
||||
ui->triggerCapture->setEnabled(true);
|
||||
ui->triggerCapture->setText(tr("Trigger Capture"));
|
||||
ui->triggerCapture->setText(tr("Trigger After Delay"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -700,12 +702,6 @@ bool LiveCapture::checkAllowClose()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(res == QMessageBox::No)
|
||||
{
|
||||
// treat this capture as saved now, so we don't prompt about it again.
|
||||
cap->saved = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_IgnoreThreadClosed = false;
|
||||
@@ -1097,13 +1093,15 @@ void LiveCapture::connectionThreadEntry()
|
||||
{
|
||||
m_Connection->TriggerCapture((uint)m_CaptureNumFrames);
|
||||
m_TriggerCapture = false;
|
||||
m_CaptureNumFrames = 1;
|
||||
}
|
||||
|
||||
if(m_QueueCapture)
|
||||
{
|
||||
m_Connection->QueueCapture((uint)m_CaptureFrameNum);
|
||||
m_Connection->QueueCapture((uint32_t)m_QueueCaptureFrameNum, (uint32_t)m_CaptureNumFrames);
|
||||
m_QueueCapture = false;
|
||||
m_CaptureFrameNum = 0;
|
||||
m_QueueCaptureFrameNum = 0;
|
||||
m_CaptureNumFrames = 1;
|
||||
}
|
||||
|
||||
if(!m_CopyCaptureLocalPath.isEmpty())
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
~LiveCapture();
|
||||
|
||||
void QueueCapture(int frameNumber);
|
||||
void QueueCapture(int frameNumber, int numFrames);
|
||||
const QString &hostname() { return m_Hostname; }
|
||||
void cleanItems();
|
||||
|
||||
@@ -161,7 +161,7 @@ private:
|
||||
bool m_TriggerCapture = false;
|
||||
bool m_QueueCapture = false;
|
||||
int m_CaptureNumFrames = 1;
|
||||
int m_CaptureFrameNum = 0;
|
||||
int m_QueueCaptureFrameNum = 0;
|
||||
int m_CaptureCounter = 0;
|
||||
QSemaphore m_Disconnect;
|
||||
ITargetControl *m_Connection = NULL;
|
||||
|
||||
@@ -177,27 +177,7 @@
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QDoubleSpinBox" name="captureFrame">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QPushButton" name="queueCap">
|
||||
<property name="text">
|
||||
<string>Queue Capture</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="captureDelay">
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
@@ -219,7 +199,34 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="captureFrame">
|
||||
<property name="prefix">
|
||||
<string>Frame </string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="triggerCapture">
|
||||
<property name="text">
|
||||
<string>Trigger After Delay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="queueCap">
|
||||
<property name="text">
|
||||
<string>Queue Specific Frame</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QDoubleSpinBox" name="numFrames">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@@ -227,6 +234,12 @@
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Capture </string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> Sequential Frame(s)</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@@ -236,43 +249,12 @@
|
||||
<property name="maximum">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="capDelayLabel">
|
||||
<property name="text">
|
||||
<string>Capture Delay</string>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="numFramesLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string># Frames:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QPushButton" name="triggerCapture">
|
||||
<property name="text">
|
||||
<string>Trigger Capture</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="capFrameLabel">
|
||||
<property name="text">
|
||||
<string>Capture Frame #</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="5" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
||||
@@ -1170,9 +1170,14 @@ next after that.
|
||||
DOCUMENT(R"(Queue up a capture to happen on a particular frame number. When this frame is about to
|
||||
begin a capture is begun, and it ends when this frame number ends.
|
||||
|
||||
.. note:: Frame 0 is defined as starting when the device is created, up to the first swapchain
|
||||
present defined frame boundary.
|
||||
|
||||
:param int frameNumber: The number of the frame to capture on.
|
||||
:param int numFrames: How many frames to capture. These will be captured sequentially and
|
||||
independently to separate files.
|
||||
)");
|
||||
virtual void QueueCapture(uint32_t frameNumber) = 0;
|
||||
virtual void QueueCapture(uint32_t frameNumber, uint32_t numFrames) = 0;
|
||||
|
||||
DOCUMENT(R"(Begin copying a given capture stored on a remote machine to the local machine over the
|
||||
target control connection.
|
||||
|
||||
@@ -682,7 +682,7 @@ bool RenderDoc::ShouldTriggerCapture(uint32_t frameNumber)
|
||||
{
|
||||
// discard, this frame is past.
|
||||
}
|
||||
else if((*it) - 1 == frameNumber)
|
||||
else if((*it) == frameNumber)
|
||||
{
|
||||
// we want to capture the next frame
|
||||
ret = true;
|
||||
|
||||
@@ -249,7 +249,7 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
|
||||
|
||||
if(type == ePacket_TriggerCapture)
|
||||
{
|
||||
uint32_t numFrames;
|
||||
uint32_t numFrames = 1;
|
||||
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(numFrames);
|
||||
@@ -258,12 +258,15 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
|
||||
}
|
||||
else if(type == ePacket_QueueCapture)
|
||||
{
|
||||
uint32_t frameNum;
|
||||
uint32_t frameNum = 0;
|
||||
uint32_t numFrames = 1;
|
||||
|
||||
READ_DATA_SCOPE();
|
||||
SERIALISE_ELEMENT(frameNum);
|
||||
SERIALISE_ELEMENT(numFrames);
|
||||
|
||||
RenderDoc::Inst().QueueCapture(frameNum);
|
||||
for(uint32_t f = 0; f < numFrames; f++)
|
||||
RenderDoc::Inst().QueueCapture(frameNum + f);
|
||||
}
|
||||
else if(type == ePacket_DeleteCapture)
|
||||
{
|
||||
@@ -537,12 +540,13 @@ public:
|
||||
SAFE_DELETE(m_Socket);
|
||||
}
|
||||
|
||||
void QueueCapture(uint32_t frameNumber)
|
||||
void QueueCapture(uint32_t frameNumber, uint32_t numFrames)
|
||||
{
|
||||
WRITE_DATA_SCOPE();
|
||||
SCOPED_SERIALISE_CHUNK(ePacket_QueueCapture);
|
||||
|
||||
SERIALISE_ELEMENT(frameNumber);
|
||||
SERIALISE_ELEMENT(numFrames);
|
||||
|
||||
if(ser.IsErrored())
|
||||
SAFE_DELETE(m_Socket);
|
||||
|
||||
@@ -1356,10 +1356,10 @@ void WrappedID3D11Device::StartFrameCapture(void *dev, void *wnd)
|
||||
m_FailedFrame = 0;
|
||||
m_FailedReason = CaptureSucceeded;
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter + 1;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
m_CapturedFrames.push_back(frame);
|
||||
|
||||
@@ -1650,8 +1650,8 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
}
|
||||
|
||||
RDCFile *rdc = RenderDoc::Inst().CreateRDC(RDCDriver::D3D11, m_FrameCounter, jpgbuf, len,
|
||||
thwidth, thheight);
|
||||
RDCFile *rdc = RenderDoc::Inst().CreateRDC(
|
||||
RDCDriver::D3D11, m_CapturedFrames.back().frameNumber, jpgbuf, len, thwidth, thheight);
|
||||
|
||||
SAFE_DELETE_ARRAY(jpgbuf);
|
||||
SAFE_DELETE_ARRAY(thpixels);
|
||||
@@ -1744,7 +1744,7 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
UnlockForChunkFlushing();
|
||||
}
|
||||
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_FrameCounter);
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
m_State = CaptureState::BackgroundCapturing;
|
||||
|
||||
@@ -1803,7 +1803,7 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
old.ApplyState(m_pImmediateContext);
|
||||
}
|
||||
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter + 1;
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
|
||||
m_pImmediateContext->CleanupCapture();
|
||||
|
||||
|
||||
@@ -1247,10 +1247,10 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
m_SubmitCounter = 0;
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter + 1;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
@@ -1580,8 +1580,8 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
if((*it)->GetResourceRecord()->ContainsExecuteIndirect)
|
||||
WrappedID3D12Resource::RefBuffers(GetResourceManager());
|
||||
|
||||
rdc = RenderDoc::Inst().CreateRDC(RDCDriver::D3D12, m_FrameCounter, jpgbuf, len, thwidth,
|
||||
thheight);
|
||||
rdc = RenderDoc::Inst().CreateRDC(RDCDriver::D3D12, m_CapturedFrames.back().frameNumber, jpgbuf,
|
||||
len, thwidth, thheight);
|
||||
|
||||
SAFE_DELETE_ARRAY(jpgbuf);
|
||||
SAFE_DELETE_ARRAY(thpixels);
|
||||
@@ -1684,7 +1684,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
RDCDEBUG("Done");
|
||||
}
|
||||
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_FrameCounter);
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
SAFE_DELETE(m_HeaderChunk);
|
||||
|
||||
|
||||
@@ -1560,10 +1560,10 @@ void WrappedOpenGL::StartFrameCapture(void *dev, void *wnd)
|
||||
GLWindowingData switchctx = prevctx;
|
||||
MakeValidContextCurrent(switchctx, wnd);
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter + 1;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
@@ -1641,8 +1641,9 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
if(bbim == NULL)
|
||||
bbim = SaveBackbufferImage();
|
||||
|
||||
RDCFile *rdc = RenderDoc::Inst().CreateRDC(GetDriverType(), m_FrameCounter, bbim->jpgbuf,
|
||||
bbim->len, bbim->thwidth, bbim->thheight);
|
||||
RDCFile *rdc =
|
||||
RenderDoc::Inst().CreateRDC(GetDriverType(), m_CapturedFrames.back().frameNumber,
|
||||
bbim->jpgbuf, bbim->len, bbim->thwidth, bbim->thheight);
|
||||
|
||||
SAFE_DELETE(bbim);
|
||||
|
||||
@@ -1730,7 +1731,7 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
}
|
||||
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_FrameCounter);
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
m_State = CaptureState::BackgroundCapturing;
|
||||
|
||||
@@ -1773,7 +1774,7 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
ClearGLErrors(m_Real);
|
||||
}
|
||||
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter + 1;
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
|
||||
CleanupCapture();
|
||||
|
||||
|
||||
@@ -927,10 +927,10 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
m_SubmitCounter = 0;
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter + 1;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
@@ -1335,8 +1335,8 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
}
|
||||
|
||||
RDCFile *rdc =
|
||||
RenderDoc::Inst().CreateRDC(RDCDriver::Vulkan, m_FrameCounter, jpgbuf, len, thwidth, thheight);
|
||||
RDCFile *rdc = RenderDoc::Inst().CreateRDC(RDCDriver::Vulkan, m_CapturedFrames.back().frameNumber,
|
||||
jpgbuf, len, thwidth, thheight);
|
||||
|
||||
SAFE_DELETE_ARRAY(jpgbuf);
|
||||
SAFE_DELETE_ARRAY(thpixels);
|
||||
@@ -1429,7 +1429,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
}
|
||||
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_FrameCounter);
|
||||
RenderDoc::Inst().FinishCaptureWriting(rdc, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
SAFE_DELETE(m_HeaderChunk);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user