mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-30 03:11:12 +00:00
Remove assumptions that captures are always frames
* Previously we had "Frame X" and "Start of Frame" hardcoded in the event browser, and the end of frame was in many cases assumed to be a present call. However with the in-application API this is not necessarily true. * Presents are now serialised separately in all APIs and displayed wherever they happen in the frame, and if there is no present at the end of the frame an "End of Capture" marker is inserted. Similarly API-defined captures are not given a potentially misleading frame number.
This commit is contained in:
@@ -355,10 +355,30 @@ void LiveCapture::saveCapture_triggered()
|
||||
if(path.endsWith(lit(".rdc")))
|
||||
path.chop(4);
|
||||
|
||||
// don't save duplicates if we have multiple captures from the same frame (possible if the
|
||||
// application is not presenting at all and using the API to capture)
|
||||
QMap<uint32_t, uint32_t> existingFiles;
|
||||
|
||||
for(QListWidgetItem *item : ui->captures->selectedItems())
|
||||
{
|
||||
Capture *cap = GetCapture(item);
|
||||
saveCapture(cap, QFormatStr("%1-frame%2.rdc").arg(path).arg(cap->frameNumber));
|
||||
|
||||
QString filename = QFormatStr("%1-frame%2").arg(path).arg(cap->frameNumber);
|
||||
if(cap->frameNumber == ~0U)
|
||||
filename = QFormatStr("%1-capture").arg(path);
|
||||
|
||||
if(existingFiles.contains(cap->frameNumber))
|
||||
{
|
||||
filename += QFormatStr("_%1").arg(existingFiles[cap->frameNumber]);
|
||||
existingFiles[cap->frameNumber]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// start on 2 next time
|
||||
existingFiles[cap->frameNumber] = 2;
|
||||
}
|
||||
|
||||
saveCapture(cap, QFormatStr("%1.rdc").arg(filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -652,8 +672,12 @@ QString LiveCapture::MakeText(Capture *cap)
|
||||
text += tr(" (Remote)");
|
||||
|
||||
text += lit("\n") + cap->api;
|
||||
text += tr("\nFrame #%1 ").arg(cap->frameNumber) +
|
||||
cap->timestamp.toString(lit("yyyy-MM-dd HH:mm:ss"));
|
||||
if(cap->frameNumber == ~0U)
|
||||
text += tr("\nUser-defined Capture ");
|
||||
else
|
||||
text += tr("\nFrame #%1 ").arg(cap->frameNumber);
|
||||
|
||||
text += cap->timestamp.toString(lit("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
return text;
|
||||
}
|
||||
@@ -687,10 +711,14 @@ bool LiveCapture::checkAllowClose()
|
||||
|
||||
if(!suppressRemoteWarning && !notoall)
|
||||
{
|
||||
QString frameName = tr("Frame #%1").arg(cap->frameNumber);
|
||||
if(cap->frameNumber == ~0U)
|
||||
frameName = tr("User-defined Capture");
|
||||
|
||||
res = RDDialog::question(this, tr("Unsaved capture"),
|
||||
tr("Save this capture '%1 Frame #%2' at %3?")
|
||||
tr("Save this capture '%1 %2' at %3?")
|
||||
.arg(cap->name)
|
||||
.arg(cap->frameNumber)
|
||||
.arg(frameName)
|
||||
.arg(cap->timestamp.toString(lit("HH:mm:ss"))),
|
||||
msgFlags);
|
||||
|
||||
|
||||
@@ -238,11 +238,15 @@ EventBrowser::~EventBrowser()
|
||||
|
||||
void EventBrowser::OnCaptureLoaded()
|
||||
{
|
||||
RDTreeWidgetItem *frame = new RDTreeWidgetItem(
|
||||
{QFormatStr("Frame #%1").arg(m_Ctx.FrameInfo().frameNumber), QString(), QString(), QString()});
|
||||
uint32_t frameNumber = m_Ctx.FrameInfo().frameNumber;
|
||||
|
||||
QString rootName =
|
||||
frameNumber == ~0U ? tr("User-defined Capture") : tr("Frame #%1").arg(frameNumber);
|
||||
|
||||
RDTreeWidgetItem *frame = new RDTreeWidgetItem({rootName, QString(), QString(), QString()});
|
||||
|
||||
RDTreeWidgetItem *framestart =
|
||||
new RDTreeWidgetItem({tr("Frame Start"), lit("0"), lit("0"), QString()});
|
||||
new RDTreeWidgetItem({tr("Capture Start"), lit("0"), lit("0"), QString()});
|
||||
framestart->setTag(QVariant::fromValue(EventItemTag(0, 0)));
|
||||
|
||||
frame->addChild(framestart);
|
||||
|
||||
@@ -369,7 +369,9 @@ div.stage table tr td { border-right: 1px solid #AAAAAA; background-color: #EEEE
|
||||
|
||||
xml.writeStartElement(lit("h3"));
|
||||
{
|
||||
QString context = tr("Frame %1").arg(m_Ctx.FrameInfo().frameNumber);
|
||||
uint32_t frameNumber = m_Ctx.FrameInfo().frameNumber;
|
||||
|
||||
QString context = frameNumber == ~0U ? tr("Capture") : tr("Frame %1").arg(frameNumber);
|
||||
|
||||
const DrawcallDescription *draw = m_Ctx.CurDrawcall();
|
||||
|
||||
|
||||
@@ -187,7 +187,12 @@ void TimelineBar::OnCaptureClosed()
|
||||
|
||||
void TimelineBar::OnCaptureLoaded()
|
||||
{
|
||||
setWindowTitle(tr("Timeline - Frame #%1").arg(m_Ctx.FrameInfo().frameNumber));
|
||||
uint32_t frameNumber = m_Ctx.FrameInfo().frameNumber;
|
||||
|
||||
if(frameNumber != ~0U)
|
||||
setWindowTitle(tr("Timeline - Frame #%1").arg(frameNumber));
|
||||
else
|
||||
setWindowTitle(tr("Timeline - Capture"));
|
||||
|
||||
processDraws(m_RootMarkers, m_RootDraws, m_Ctx.CurDrawcalls());
|
||||
|
||||
|
||||
@@ -1060,7 +1060,12 @@ struct FrameStatistics
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(FrameStatistics);
|
||||
|
||||
DOCUMENT("Contains frame-level global information");
|
||||
DOCUMENT(R"(Contains frame-level global information
|
||||
|
||||
.. data:: NoFrameNumber
|
||||
|
||||
No frame number is available.
|
||||
)");
|
||||
struct FrameDescription
|
||||
{
|
||||
DOCUMENT("");
|
||||
@@ -1080,7 +1085,8 @@ struct FrameDescription
|
||||
this counts the frame number when the capture was made.
|
||||
|
||||
.. note:: This value is only accurate if the capture was triggered through the default mechanism, if
|
||||
it was triggered from the application API it doesn't correspond to anything.
|
||||
it was triggered from the application API it doesn't correspond to anything and will be set to
|
||||
:data:`NoFrameNumber`.
|
||||
)");
|
||||
uint32_t frameNumber;
|
||||
|
||||
@@ -1111,6 +1117,8 @@ this counts the frame number when the capture was made.
|
||||
|
||||
DOCUMENT("A list of debug messages that are not associated with any particular event.");
|
||||
rdcarray<DebugMessage> debugMessages;
|
||||
|
||||
static const uint32_t NoFrameNumber = ~0U;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(FrameDescription);
|
||||
|
||||
+11
-3
@@ -857,7 +857,10 @@ std::string RenderDoc::GetOverlayText(RDCDriver driver, uint32_t frameNumber, in
|
||||
{
|
||||
if(now - m_Captures[i].timestamp < 20)
|
||||
{
|
||||
overlayText += StringFormat::Fmt("Captured frame %d.\n", m_Captures[i].frameNumber);
|
||||
if(m_Captures[i].frameNumber == ~0U)
|
||||
overlayText += "Captured user-defined capture.\n";
|
||||
else
|
||||
overlayText += StringFormat::Fmt("Captured frame %d.\n", m_Captures[i].frameNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1061,7 +1064,12 @@ RDCFile *RenderDoc::CreateRDC(RDCDriver driver, uint32_t frameNum, const FramePi
|
||||
{
|
||||
RDCFile *ret = new RDCFile;
|
||||
|
||||
m_CurrentLogFile = StringFormat::Fmt("%s_frame%u.rdc", m_CaptureFileTemplate.c_str(), frameNum);
|
||||
std::string suffix = StringFormat::Fmt("_frame%u", frameNum);
|
||||
|
||||
if(frameNum == ~0U)
|
||||
suffix = "_capture";
|
||||
|
||||
m_CurrentLogFile = StringFormat::Fmt("%s%s.rdc", m_CaptureFileTemplate.c_str(), suffix.c_str());
|
||||
|
||||
// make sure we don't stomp another capture if we make multiple captures in the same frame.
|
||||
{
|
||||
@@ -1072,7 +1080,7 @@ RDCFile *RenderDoc::CreateRDC(RDCDriver driver, uint32_t frameNum, const FramePi
|
||||
}) != m_Captures.end())
|
||||
{
|
||||
m_CurrentLogFile =
|
||||
StringFormat::Fmt("%s_frame%u_%d.rdc", m_CaptureFileTemplate.c_str(), frameNum, altnum);
|
||||
StringFormat::Fmt("%s%s_%d.rdc", m_CaptureFileTemplate.c_str(), suffix.c_str(), altnum);
|
||||
altnum++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,8 +162,6 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
|
||||
m_FailureReason = CaptureSucceeded;
|
||||
m_EmptyCommandList = true;
|
||||
|
||||
m_PresentChunk = false;
|
||||
|
||||
m_DrawcallStack.push_back(&m_ParentDrawcall);
|
||||
|
||||
m_CurEventID = 0;
|
||||
@@ -543,15 +541,47 @@ void WrappedID3D11DeviceContext::EndCaptureFrame()
|
||||
m_ContextRecord->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
void WrappedID3D11DeviceContext::Present(UINT SyncInterval, UINT Flags)
|
||||
template <typename SerialiserType>
|
||||
bool WrappedID3D11DeviceContext::Serialise_Present(SerialiserType &ser, UINT SyncInterval, UINT Flags)
|
||||
{
|
||||
WriteSerialiser &ser = m_ScratchSerialiser;
|
||||
SCOPED_SERIALISE_CHUNK(D3D11Chunk::SwapchainPresent);
|
||||
SERIALISE_ELEMENT(m_ResourceID).Named("Context"_lit).TypedAs("ID3D11DeviceContext *"_lit);
|
||||
// we don't do anything with these parameters, they're just here to store
|
||||
// them for user benefits
|
||||
SERIALISE_ELEMENT(SyncInterval);
|
||||
SERIALISE_ELEMENT(Flags);
|
||||
|
||||
m_ContextRecord->AddChunk(scope.Get());
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading() && IsLoading(m_State))
|
||||
{
|
||||
AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
|
||||
draw.copyDestination = m_pDevice->GetBackbufferResourceID();
|
||||
|
||||
draw.name = StringFormat::Fmt("Present(%s)", ToStr(draw.copyDestination).c_str());
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
AddDrawcall(draw, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WrappedID3D11DeviceContext::Present(UINT SyncInterval, UINT Flags)
|
||||
{
|
||||
SERIALISE_TIME_CALL();
|
||||
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
USE_SCRATCH_SERIALISER();
|
||||
GET_SERIALISER.SetDrawChunk();
|
||||
SCOPED_SERIALISE_CHUNK(D3D11Chunk::SwapchainPresent);
|
||||
SERIALISE_ELEMENT(m_ResourceID).Named("Context"_lit).TypedAs("ID3D11DeviceContext *"_lit);
|
||||
Serialise_Present(ser, SyncInterval, Flags);
|
||||
|
||||
m_ContextRecord->AddChunk(scope.Get());
|
||||
}
|
||||
}
|
||||
|
||||
bool WrappedID3D11DeviceContext::ShadowStorageInUse(D3D11ResourceRecord *record)
|
||||
@@ -827,34 +857,17 @@ bool WrappedID3D11DeviceContext::ProcessChunk(ReadSerialiser &ser, D3D11Chunk ch
|
||||
ret = Serialise_SwapDeviceContextState(ser, NULL, NULL);
|
||||
break;
|
||||
|
||||
case D3D11Chunk::SwapchainPresent:
|
||||
{
|
||||
// we don't do anything with these parameters, they're just here to store
|
||||
// them for user benefits
|
||||
UINT SyncInterval = 0, Flags = 0;
|
||||
SERIALISE_ELEMENT(SyncInterval);
|
||||
SERIALISE_ELEMENT(Flags);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
ret = true;
|
||||
|
||||
m_PresentChunk = true;
|
||||
break;
|
||||
}
|
||||
case D3D11Chunk::SwapchainPresent: ret = Serialise_Present(ser, 0, 0); break;
|
||||
default:
|
||||
{
|
||||
SystemChunk system = (SystemChunk)chunk;
|
||||
|
||||
if(system == SystemChunk::CaptureEnd)
|
||||
{
|
||||
if(IsLoading(m_State))
|
||||
if(IsLoading(m_State) && m_LastChunk != D3D11Chunk::SwapchainPresent)
|
||||
{
|
||||
if(!m_PresentChunk)
|
||||
AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
draw.name = "End of Frame";
|
||||
draw.name = "End of Capture";
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
draw.copyDestination = m_pDevice->GetBackbufferResourceID();
|
||||
@@ -1200,6 +1213,7 @@ ReplayStatus WrappedID3D11DeviceContext::ReplayLog(CaptureState readType, uint32
|
||||
if((SystemChunk)chunktype == SystemChunk::CaptureEnd)
|
||||
break;
|
||||
|
||||
m_LastChunk = chunktype;
|
||||
m_CurEventID++;
|
||||
}
|
||||
|
||||
|
||||
@@ -176,8 +176,6 @@ private:
|
||||
RenderDoc::Inst().AddActiveDriver(RDCDriver::D3D11, false);
|
||||
}
|
||||
|
||||
bool m_PresentChunk;
|
||||
|
||||
ResourceId m_FakeContext;
|
||||
|
||||
bool m_DoStateVerify;
|
||||
@@ -212,6 +210,7 @@ private:
|
||||
uint64_t m_CurChunkOffset;
|
||||
SDChunkMetaData m_ChunkMetadata;
|
||||
uint32_t m_CurEventID, m_CurDrawcallID;
|
||||
D3D11Chunk m_LastChunk;
|
||||
|
||||
ReplayStatus m_FailedReplayStatus = ReplayStatus::APIReplayFailed;
|
||||
|
||||
@@ -287,7 +286,7 @@ public:
|
||||
void MarkDirtyResource(ResourceId id);
|
||||
|
||||
// insert a fake chunk just to store these parameters
|
||||
void Present(UINT SyncInterval, UINT Flags);
|
||||
IMPLEMENT_FUNCTION_SERIALISED(void, Present, UINT SyncInterval, UINT Flags);
|
||||
|
||||
void CleanupCapture();
|
||||
bool ShadowStorageInUse(D3D11ResourceRecord *record);
|
||||
|
||||
@@ -101,15 +101,10 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara
|
||||
m_WrappedMultithread.m_pDevice = this;
|
||||
m_WrappedVideo.m_pDevice = this;
|
||||
|
||||
m_FrameCounter = 0;
|
||||
m_FailedFrame = 0;
|
||||
m_FailedReason = CaptureSucceeded;
|
||||
m_Failures = 0;
|
||||
|
||||
m_ChunkAtomic = 0;
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
m_State = CaptureState::LoadingReplaying;
|
||||
@@ -1084,13 +1079,13 @@ bool WrappedID3D11Device::ProcessChunk(ReadSerialiser &ser, D3D11Chunk context)
|
||||
template <typename SerialiserType>
|
||||
bool WrappedID3D11Device::Serialise_CaptureScope(SerialiserType &ser)
|
||||
{
|
||||
SERIALISE_ELEMENT(m_FrameCounter);
|
||||
SERIALISE_ELEMENT_LOCAL(frameNumber, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayMode(m_State))
|
||||
{
|
||||
m_FrameRecord.frameInfo.frameNumber = m_FrameCounter;
|
||||
m_FrameRecord.frameInfo.frameNumber = frameNumber;
|
||||
|
||||
FrameStatistics &stats = m_FrameRecord.frameInfo.stats;
|
||||
RDCEraseEl(stats);
|
||||
@@ -1566,10 +1561,10 @@ void WrappedID3D11Device::StartFrameCapture(void *dev, void *wnd)
|
||||
m_FailedFrame = 0;
|
||||
m_FailedReason = CaptureSucceeded;
|
||||
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
// for app-controlled captures the frame number is meaningless, so set it here here first. We'll
|
||||
// update it with the actual frame counter when we un-set m_AppControlledCapture.
|
||||
frame.frameNumber = ~0U;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
m_CapturedFrames.push_back(frame);
|
||||
|
||||
@@ -1603,7 +1598,7 @@ void WrappedID3D11Device::StartFrameCapture(void *dev, void *wnd)
|
||||
if(m_pInfoQueue)
|
||||
m_pInfoQueue->ClearStoredMessages();
|
||||
|
||||
RDCLOG("Starting capture, frame %u", m_FrameCounter);
|
||||
RDCLOG("Starting capture, frame %u", m_CapturedFrames.back().frameNumber);
|
||||
}
|
||||
|
||||
bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
@@ -1637,7 +1632,10 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
|
||||
if(m_pImmediateContext->HasSuccessfulCapture(reason))
|
||||
{
|
||||
RDCLOG("Finished capture, Frame %u", m_FrameCounter);
|
||||
RDCLOG("Finished capture, Frame %u", m_CapturedFrames.back().frameNumber);
|
||||
|
||||
if(swapper == NULL)
|
||||
swapper = m_LastSwap;
|
||||
|
||||
m_Failures = 0;
|
||||
m_FailedFrame = 0;
|
||||
@@ -1906,7 +1904,7 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
default: break;
|
||||
}
|
||||
|
||||
RDCLOG("Failed to capture, frame %u: %s", m_FrameCounter, reasonString);
|
||||
RDCLOG("Failed to capture, frame %u: %s", m_CapturedFrames.back().frameNumber, reasonString);
|
||||
|
||||
m_Failures++;
|
||||
|
||||
@@ -1923,14 +1921,16 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
m_TextRenderer->SetOutputDimensions(swapper->GetWidth(), swapper->GetHeight());
|
||||
m_TextRenderer->SetOutputWindow(swapper->GetHWND());
|
||||
|
||||
m_TextRenderer->RenderText(0.0f, 0.0f, "Failed to capture frame %u: %s", m_FrameCounter,
|
||||
reasonString);
|
||||
m_TextRenderer->RenderText(0.0f, 0.0f, "Failed to capture frame %u: %s",
|
||||
m_CapturedFrames.back().frameNumber, reasonString);
|
||||
}
|
||||
|
||||
old.ApplyState(m_pImmediateContext);
|
||||
}
|
||||
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
uint32_t failedFrame = m_CapturedFrames.back().frameNumber;
|
||||
|
||||
m_CapturedFrames.back().frameNumber = m_AppControlledCapture ? ~0U : m_FrameCounter;
|
||||
|
||||
m_pImmediateContext->CleanupCapture();
|
||||
|
||||
@@ -1973,7 +1973,7 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
|
||||
|
||||
GetResourceManager()->FreeCaptureData();
|
||||
|
||||
m_FailedFrame = m_FrameCounter;
|
||||
m_FailedFrame = failedFrame;
|
||||
m_FailedReason = reason;
|
||||
|
||||
m_State = CaptureState::BackgroundCapturing;
|
||||
@@ -2180,6 +2180,7 @@ void WrappedID3D11Device::FirstFrame(IDXGISwapper *swapper)
|
||||
RenderDoc::Inst().StartFrameCapture((ID3D11Device *)this, swapper->GetHWND());
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2201,6 +2202,8 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapper *swapper, UINT SyncInterval, U
|
||||
|
||||
bool activeWindow = RenderDoc::Inst().IsActiveWindow((ID3D11Device *)this, swapper->GetHWND());
|
||||
|
||||
m_LastSwap = swapper;
|
||||
|
||||
if(IsBackgroundCapturing(m_State))
|
||||
{
|
||||
D3D11RenderState old = *m_pImmediateContext->GetCurrentPipelineState();
|
||||
@@ -2243,14 +2246,16 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapper *swapper, UINT SyncInterval, U
|
||||
|
||||
RenderDoc::Inst().AddActiveDriver(RDCDriver::D3D11, true);
|
||||
|
||||
// serialise the present call, even for inactive windows
|
||||
if(IsActiveCapturing(m_State))
|
||||
m_pImmediateContext->Present(SyncInterval, Flags);
|
||||
|
||||
if(!activeWindow)
|
||||
return S_OK;
|
||||
|
||||
// kill any current capture that isn't application defined
|
||||
if(IsActiveCapturing(m_State) && !m_AppControlledCapture)
|
||||
{
|
||||
m_pImmediateContext->Present(SyncInterval, Flags);
|
||||
|
||||
RenderDoc::Inst().EndFrameCapture((ID3D11Device *)this, swapper->GetHWND());
|
||||
}
|
||||
|
||||
@@ -2259,6 +2264,7 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapper *swapper, UINT SyncInterval, U
|
||||
RenderDoc::Inst().StartFrameCapture((ID3D11Device *)this, swapper->GetHWND());
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
@@ -345,7 +345,7 @@ private:
|
||||
D3D11ResourceRecord *m_DeviceRecord;
|
||||
|
||||
CaptureState m_State;
|
||||
bool m_AppControlledCapture;
|
||||
bool m_AppControlledCapture = false;
|
||||
|
||||
ReplayStatus m_FailedReplayStatus = ReplayStatus::APIReplayFailed;
|
||||
|
||||
@@ -374,10 +374,12 @@ private:
|
||||
|
||||
std::map<IDXGISwapper *, ID3D11RenderTargetView *> m_SwapChains;
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
uint32_t m_FailedFrame;
|
||||
IDXGISwapper *m_LastSwap = NULL;
|
||||
|
||||
uint32_t m_FrameCounter = 0;
|
||||
uint32_t m_FailedFrame = 0;
|
||||
CaptureFailReason m_FailedReason;
|
||||
uint32_t m_Failures;
|
||||
uint32_t m_Failures = 0;
|
||||
|
||||
SDFile *m_StructuredFile = NULL;
|
||||
SDFile m_StoredStructuredData;
|
||||
|
||||
@@ -133,7 +133,6 @@ class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
|
||||
D3D12CommandData m_Cmd;
|
||||
|
||||
ResourceId m_PrevQueueId;
|
||||
ResourceId m_BackbufferID;
|
||||
|
||||
bool ProcessChunk(ReadSerialiser &ser, D3D12Chunk context);
|
||||
|
||||
@@ -155,7 +154,6 @@ public:
|
||||
D3D12DrawcallTreeNode &GetParentDrawcall() { return m_Cmd.m_ParentDrawcall; }
|
||||
const APIEvent &GetEvent(uint32_t eventId);
|
||||
uint32_t GetMaxEID() { return m_Cmd.m_Events.back().eventId; }
|
||||
ResourceId GetBackbufferResourceID() { return m_BackbufferID; }
|
||||
void ClearAfterCapture();
|
||||
|
||||
ReplayStatus ReplayLog(CaptureState readType, uint32_t startEventID, uint32_t endEventID,
|
||||
|
||||
@@ -706,6 +706,8 @@ bool WrappedID3D12CommandQueue::ProcessChunk(ReadSerialiser &ser, D3D12Chunk chu
|
||||
// Just in case it gets exported and imported, completely ignore it.
|
||||
return true;
|
||||
|
||||
case D3D12Chunk::Swapchain_Present: ret = m_pDevice->Serialise_Present(ser, NULL, 0, 0); break;
|
||||
|
||||
default:
|
||||
{
|
||||
SystemChunk system = (SystemChunk)chunk;
|
||||
@@ -716,17 +718,18 @@ bool WrappedID3D12CommandQueue::ProcessChunk(ReadSerialiser &ser, D3D12Chunk chu
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
m_BackbufferID = PresentedImage;
|
||||
if(PresentedImage != ResourceId())
|
||||
m_Cmd.m_LastPresentedImage = PresentedImage;
|
||||
|
||||
if(IsLoading(m_State))
|
||||
if(IsLoading(m_State) && m_Cmd.m_LastChunk != D3D12Chunk::Swapchain_Present)
|
||||
{
|
||||
m_Cmd.AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
draw.name = "Present()";
|
||||
draw.name = "End of Capture";
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
draw.copyDestination = m_BackbufferID;
|
||||
draw.copyDestination = m_Cmd.m_LastPresentedImage;
|
||||
|
||||
m_Cmd.AddDrawcall(draw, true);
|
||||
}
|
||||
@@ -895,6 +898,8 @@ ReplayStatus WrappedID3D12CommandQueue::ReplayLog(CaptureState readType, uint32_
|
||||
if(IsActiveReplaying(m_State) && startEventID == endEventID)
|
||||
break;
|
||||
|
||||
m_Cmd.m_LastChunk = context;
|
||||
|
||||
// increment root event ID either if we didn't just replay a cmd
|
||||
// buffer event, OR if we are doing a frame sub-section replay,
|
||||
// in which case it's up to the calling code to make sure we only
|
||||
|
||||
@@ -338,6 +338,9 @@ struct D3D12CommandData
|
||||
SDChunkMetaData m_ChunkMetadata;
|
||||
uint32_t m_RootEventID, m_RootDrawcallID;
|
||||
uint32_t m_FirstEventID, m_LastEventID;
|
||||
D3D12Chunk m_LastChunk;
|
||||
|
||||
ResourceId m_LastPresentedImage;
|
||||
|
||||
SDFile *m_StructuredFile;
|
||||
|
||||
|
||||
@@ -827,5 +827,6 @@ enum class D3D12Chunk : uint32_t
|
||||
List_RSSetShadingRate,
|
||||
List_RSSetShadingRateImage,
|
||||
Device_ExternalDXGIResource,
|
||||
Swapchain_Present,
|
||||
Max,
|
||||
};
|
||||
|
||||
@@ -264,13 +264,9 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
|
||||
|
||||
m_Replay.SetDevice(this);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
|
||||
threadSerialiserTLSSlot = Threading::AllocateTLSSlot();
|
||||
tempMemoryTLSSlot = Threading::AllocateTLSSlot();
|
||||
|
||||
m_FrameCounter = 0;
|
||||
|
||||
m_HeaderChunk = NULL;
|
||||
|
||||
m_Alloc = m_DataUploadAlloc = NULL;
|
||||
@@ -354,7 +350,6 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
|
||||
m_DeviceRecord = NULL;
|
||||
|
||||
m_Queue = NULL;
|
||||
m_LastSwap = NULL;
|
||||
|
||||
if(!RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
@@ -947,6 +942,7 @@ void WrappedID3D12Device::FirstFrame(IDXGISwapper *swapper)
|
||||
RenderDoc::Inst().StartFrameCapture((ID3D12Device *)this, swapper ? swapper->GetHWND() : NULL);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1613,6 +1609,24 @@ HRESULT WrappedID3D12Device::Present(ID3D12GraphicsCommandList *pOverlayCommandL
|
||||
|
||||
RenderDoc::Inst().AddActiveDriver(RDCDriver::D3D12, true);
|
||||
|
||||
// serialise the present call, even for inactive windows
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
SERIALISE_TIME_CALL();
|
||||
|
||||
ID3D12Resource *backbuffer = NULL;
|
||||
|
||||
if(swapper != NULL)
|
||||
backbuffer = (ID3D12Resource *)swapper->GetBackbuffers()[swapper->GetLastPresentedBuffer()];
|
||||
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(D3D12Chunk::Swapchain_Present);
|
||||
Serialise_Present(ser, backbuffer, SyncInterval, Flags);
|
||||
|
||||
m_FrameCaptureRecord->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
if(!activeWindow)
|
||||
return S_OK;
|
||||
|
||||
@@ -1629,21 +1643,62 @@ HRESULT WrappedID3D12Device::Present(ID3D12GraphicsCommandList *pOverlayCommandL
|
||||
RenderDoc::Inst().StartFrameCapture((ID3D12Device *)this, swapper->GetHWND());
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedID3D12Device::Serialise_Present(SerialiserType &ser, ID3D12Resource *PresentedImage,
|
||||
UINT SyncInterval, UINT Flags)
|
||||
{
|
||||
SERIALISE_ELEMENT_LOCAL(PresentedBackbuffer, GetResID(PresentedImage))
|
||||
.TypedAs("ID3D12Resource *"_lit);
|
||||
|
||||
// we don't do anything with these parameters, they're just here to store
|
||||
// them for user benefits
|
||||
SERIALISE_ELEMENT(SyncInterval);
|
||||
SERIALISE_ELEMENT(Flags);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading() && IsLoading(m_State))
|
||||
{
|
||||
D3D12CommandData &cmd = *m_Queue->GetCommandData();
|
||||
cmd.AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
|
||||
draw.name = StringFormat::Fmt("Present(%s)", ToStr(PresentedBackbuffer).c_str());
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
cmd.m_LastPresentedImage = PresentedBackbuffer;
|
||||
draw.copyDestination = PresentedBackbuffer;
|
||||
|
||||
cmd.AddDrawcall(draw, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool WrappedID3D12Device::Serialise_Present(ReadSerialiser &ser,
|
||||
ID3D12Resource *PresentedImage,
|
||||
UINT SyncInterval, UINT Flags);
|
||||
template bool WrappedID3D12Device::Serialise_Present(WriteSerialiser &ser,
|
||||
ID3D12Resource *PresentedImage,
|
||||
UINT SyncInterval, UINT Flags);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedID3D12Device::Serialise_CaptureScope(SerialiserType &ser)
|
||||
{
|
||||
SERIALISE_ELEMENT(m_FrameCounter);
|
||||
SERIALISE_ELEMENT_LOCAL(frameNumber, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayMode(m_State))
|
||||
{
|
||||
m_FrameRecord.frameInfo.frameNumber = m_FrameCounter;
|
||||
m_FrameRecord.frameInfo.frameNumber = frameNumber;
|
||||
RDCEraseEl(m_FrameRecord.frameInfo.stats);
|
||||
}
|
||||
|
||||
@@ -1681,14 +1736,14 @@ bool WrappedID3D12Device::Serialise_BeginCaptureFrame(SerialiserType &ser)
|
||||
template bool WrappedID3D12Device::Serialise_BeginCaptureFrame(ReadSerialiser &ser);
|
||||
template bool WrappedID3D12Device::Serialise_BeginCaptureFrame(WriteSerialiser &ser);
|
||||
|
||||
void WrappedID3D12Device::EndCaptureFrame(ID3D12Resource *presentImage)
|
||||
void WrappedID3D12Device::EndCaptureFrame()
|
||||
{
|
||||
WriteSerialiser &ser = GetThreadSerialiser();
|
||||
ser.SetDrawChunk();
|
||||
SCOPED_SERIALISE_CHUNK(SystemChunk::CaptureEnd);
|
||||
|
||||
SERIALISE_ELEMENT_LOCAL(PresentedBackbuffer, GetResID(presentImage))
|
||||
.TypedAs("ID3D12Resource *"_lit);
|
||||
// here for compatibility reasons, this used to store the presented Resource.
|
||||
SERIALISE_ELEMENT_LOCAL(PresentedBackbuffer, ResourceId()).Hidden();
|
||||
|
||||
m_FrameCaptureRecord->AddChunk(scope.Get());
|
||||
}
|
||||
@@ -1702,10 +1757,8 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
m_SubmitCounter = 0;
|
||||
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.frameNumber = m_AppControlledCapture ? ~0U : m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
@@ -1765,7 +1818,7 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
GetResourceManager()->MarkResourceFrameReferenced(m_ResourceID, eFrameRef_Read);
|
||||
|
||||
RDCLOG("Starting capture, frame %u", m_FrameCounter);
|
||||
RDCLOG("Starting capture, frame %u", m_CapturedFrames.back().frameNumber);
|
||||
}
|
||||
|
||||
bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
@@ -1795,7 +1848,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
}
|
||||
|
||||
RDCLOG("Finished capture, Frame %u", m_FrameCounter);
|
||||
RDCLOG("Finished capture, Frame %u", m_CapturedFrames.back().frameNumber);
|
||||
|
||||
ID3D12Resource *backbuffer = NULL;
|
||||
|
||||
@@ -1813,7 +1866,7 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
// transition back to IDLE and readback initial states atomically
|
||||
{
|
||||
SCOPED_WRITELOCK(m_CapTransitionLock);
|
||||
EndCaptureFrame(backbuffer);
|
||||
EndCaptureFrame();
|
||||
|
||||
m_State = CaptureState::BackgroundCapturing;
|
||||
|
||||
|
||||
@@ -431,14 +431,14 @@ private:
|
||||
SDFile *m_StructuredFile = NULL;
|
||||
SDFile m_StoredStructuredData;
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
uint32_t m_FrameCounter = 0;
|
||||
std::vector<FrameDescription> m_CapturedFrames;
|
||||
FrameRecord m_FrameRecord;
|
||||
std::vector<DrawcallDescription *> m_Drawcalls;
|
||||
|
||||
ReplayStatus m_FailedReplayStatus = ReplayStatus::APIReplayFailed;
|
||||
|
||||
bool m_AppControlledCapture;
|
||||
bool m_AppControlledCapture = false;
|
||||
|
||||
bool m_InvalidPSO = false;
|
||||
|
||||
@@ -492,7 +492,7 @@ private:
|
||||
std::map<IDXGISwapper *, SwapPresentInfo> m_SwapChains;
|
||||
std::map<ResourceId, DXGI_FORMAT> m_BackbufferFormat;
|
||||
|
||||
IDXGISwapper *m_LastSwap;
|
||||
IDXGISwapper *m_LastSwap = NULL;
|
||||
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Opts;
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS1 m_D3D12Opts1;
|
||||
@@ -502,7 +502,7 @@ private:
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_CaptureScope(SerialiserType &ser);
|
||||
void EndCaptureFrame(ID3D12Resource *presentImage);
|
||||
void EndCaptureFrame();
|
||||
|
||||
bool m_debugLayerEnabled;
|
||||
|
||||
@@ -653,6 +653,10 @@ public:
|
||||
bool EndFrameCapture(void *dev, void *wnd);
|
||||
bool DiscardFrameCapture(void *dev, void *wnd);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_Present(SerialiserType &ser, ID3D12Resource *PresentedImage, UINT SyncInterval,
|
||||
UINT Flags);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_BeginCaptureFrame(SerialiserType &ser);
|
||||
|
||||
|
||||
@@ -424,10 +424,13 @@ TextureDescription D3D12Replay::GetTexture(ResourceId id)
|
||||
if(desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
|
||||
ret.creationFlags |= TextureCategory::ShaderReadWrite;
|
||||
|
||||
if(ret.resourceId == m_pDevice->GetQueue()->GetBackbufferResourceID())
|
||||
{
|
||||
ret.format = MakeResourceFormat(GetTypedFormat(desc.Format, CompType::UNorm));
|
||||
ret.creationFlags |= TextureCategory::SwapBuffer;
|
||||
auto resit = m_ResourceIdx.find(ret.resourceId);
|
||||
if(resit != m_ResourceIdx.end() && m_Resources[resit->second].type == ResourceType::SwapchainImage)
|
||||
{
|
||||
ret.format = MakeResourceFormat(GetTypedFormat(desc.Format, CompType::UNorm));
|
||||
ret.creationFlags |= TextureCategory::SwapBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
template <>
|
||||
rdcstr DoStringise(const D3D12Chunk &el)
|
||||
{
|
||||
RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::Max == 1105, "Chunks changed without updating names");
|
||||
RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::Max == 1106, "Chunks changed without updating names");
|
||||
|
||||
BEGIN_ENUM_STRINGISE(D3D12Chunk)
|
||||
{
|
||||
@@ -191,6 +191,7 @@ rdcstr DoStringise(const D3D12Chunk &el)
|
||||
STRINGISE_ENUM_CLASS_NAMED(List_RSSetShadingRateImage,
|
||||
"ID3D12GraphicsCommandList5::RSSetShadingRateImage");
|
||||
STRINGISE_ENUM_CLASS_NAMED(Device_ExternalDXGIResource, "External DXGI Resource import");
|
||||
STRINGISE_ENUM_CLASS_NAMED(Swapchain_Present, "IDXGISwapChain::Present");
|
||||
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
|
||||
}
|
||||
END_ENUM_STRINGISE()
|
||||
|
||||
@@ -37,8 +37,6 @@ WrappedD3DDevice8::WrappedD3DDevice8(IDirect3DDevice8 *device, HWND wnd,
|
||||
m_DebugManager(NULL),
|
||||
m_PresentParameters(*pPresentationParameters)
|
||||
{
|
||||
m_FrameCounter = 0;
|
||||
|
||||
// refcounters implicitly construct with one reference, but we don't start with any soft
|
||||
// references.
|
||||
m_SoftRefCounter.Release();
|
||||
|
||||
@@ -228,7 +228,7 @@ private:
|
||||
RefCounter8 m_SoftRefCounter;
|
||||
bool m_Alive;
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
uint32_t m_FrameCounter = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -34,8 +34,6 @@ WrappedD3DDevice9::WrappedD3DDevice9(IDirect3DDevice9 *device, HWND wnd)
|
||||
m_device(device),
|
||||
m_DebugManager(NULL)
|
||||
{
|
||||
m_FrameCounter = 0;
|
||||
|
||||
// refcounters implicitly construct with one reference, but we don't start with any soft
|
||||
// references.
|
||||
m_SoftRefCounter.Release();
|
||||
|
||||
@@ -258,7 +258,7 @@ private:
|
||||
RefCounter9 m_SoftRefCounter;
|
||||
bool m_Alive;
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
uint32_t m_FrameCounter = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -178,6 +178,8 @@ CGLError GL_EXPORT_NAME(CGLFlushDrawable)(CGLContextObj ctx)
|
||||
|
||||
CGL.CGLGetSurface(ctx, &conn, &window, &surface);
|
||||
|
||||
gl_CurChunk = GLChunk::CGLFlushDrawable;
|
||||
|
||||
cglhook.driver.SwapBuffers(WindowingSystem::MacOS, (void *)(uintptr_t)window);
|
||||
}
|
||||
|
||||
|
||||
@@ -502,6 +502,8 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers_renderdoc_hooked(EGLDisplay dp
|
||||
|
||||
SurfaceConfig cfg = eglhook.windows[surface];
|
||||
|
||||
gl_CurChunk = GLChunk::eglSwapBuffers;
|
||||
|
||||
eglhook.driver.SwapBuffers(cfg.system, cfg.wnd);
|
||||
}
|
||||
|
||||
@@ -535,6 +537,8 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV_renderdoc_hooked(EGLDispla
|
||||
{
|
||||
SurfaceConfig cfg = eglhook.windows[surface];
|
||||
|
||||
gl_CurChunk = GLChunk::eglPostSubBufferNV;
|
||||
|
||||
eglhook.driver.SwapBuffers(cfg.system, cfg.wnd);
|
||||
}
|
||||
|
||||
@@ -568,6 +572,8 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT_renderdoc_hooked(
|
||||
{
|
||||
SurfaceConfig cfg = eglhook.windows[surface];
|
||||
|
||||
gl_CurChunk = GLChunk::eglSwapBuffersWithDamageEXT;
|
||||
|
||||
eglhook.driver.SwapBuffers(cfg.system, cfg.wnd);
|
||||
}
|
||||
|
||||
@@ -601,6 +607,8 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR_renderdoc_hooked(
|
||||
{
|
||||
SurfaceConfig cfg = eglhook.windows[surface];
|
||||
|
||||
gl_CurChunk = GLChunk::eglSwapBuffersWithDamageKHR;
|
||||
|
||||
eglhook.driver.SwapBuffers(cfg.system, cfg.wnd);
|
||||
}
|
||||
|
||||
|
||||
@@ -2163,6 +2163,15 @@ enum class GLChunk : uint32_t
|
||||
glBlendEquationARB,
|
||||
glPrimitiveBoundingBoxARB,
|
||||
|
||||
SwapBuffers,
|
||||
wglSwapBuffers,
|
||||
glXSwapBuffers,
|
||||
CGLFlushDrawable,
|
||||
eglSwapBuffers,
|
||||
eglPostSubBufferNV,
|
||||
eglSwapBuffersWithDamageEXT,
|
||||
eglSwapBuffersWithDamageKHR,
|
||||
|
||||
Max,
|
||||
};
|
||||
|
||||
|
||||
@@ -630,7 +630,6 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform)
|
||||
|
||||
m_SectionVersion = GLInitParams::CurrentVersion;
|
||||
|
||||
m_FrameCounter = 0;
|
||||
m_NoCtxFrames = 0;
|
||||
m_FailedFrame = 0;
|
||||
m_FailedReason = CaptureSucceeded;
|
||||
@@ -638,8 +637,6 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform)
|
||||
m_SuccessfulCapture = true;
|
||||
m_FailureReason = CaptureSucceeded;
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
|
||||
m_UsesVRMarkers = false;
|
||||
|
||||
m_SuppressDebugMessages = false;
|
||||
@@ -2056,6 +2053,18 @@ void WrappedOpenGL::SwapBuffers(WindowingSystem winSystem, void *windowHandle)
|
||||
m_BackbufferImages[windowHandle] = SaveBackbufferImage();
|
||||
}
|
||||
|
||||
if(IsActiveCapturing(m_State) && gl_CurChunk != GLChunk::Max)
|
||||
{
|
||||
SERIALISE_TIME_CALL();
|
||||
|
||||
USE_SCRATCH_SERIALISER();
|
||||
ser.SetDrawChunk();
|
||||
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
|
||||
Serialise_Present(ser);
|
||||
|
||||
GetContextRecord()->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
RenderDoc::Inst().AddActiveDriver(GetDriverType(), true);
|
||||
|
||||
if(!activeWindow)
|
||||
@@ -2074,6 +2083,7 @@ void WrappedOpenGL::SwapBuffers(WindowingSystem winSystem, void *windowHandle)
|
||||
RenderDoc::Inst().StartFrameCapture(ctxdata.ctx, windowHandle);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2136,10 +2146,8 @@ void WrappedOpenGL::StartFrameCapture(void *dev, void *wnd)
|
||||
GLWindowingData switchctx = prevctx;
|
||||
MakeValidContextCurrent(switchctx, wnd);
|
||||
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.frameNumber = m_AppControlledCapture ? ~0U : m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
@@ -2169,7 +2177,7 @@ void WrappedOpenGL::StartFrameCapture(void *dev, void *wnd)
|
||||
m_ActiveContexts[Threading::GetCurrentID()] = prevctx;
|
||||
}
|
||||
|
||||
RDCLOG("Starting capture, frame %u", m_FrameCounter);
|
||||
RDCLOG("Starting capture, frame %u", m_CapturedFrames.back().frameNumber);
|
||||
}
|
||||
|
||||
bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
@@ -2187,7 +2195,7 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
|
||||
if(HasSuccessfulCapture(reason))
|
||||
{
|
||||
RDCLOG("Finished capture, Frame %u", m_FrameCounter);
|
||||
RDCLOG("Finished capture, Frame %u", m_CapturedFrames.back().frameNumber);
|
||||
|
||||
m_Failures = 0;
|
||||
m_FailedFrame = 0;
|
||||
@@ -2366,7 +2374,7 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
default: break;
|
||||
}
|
||||
|
||||
RDCLOG("Failed to capture, frame %u: %s", m_FrameCounter, reasonString);
|
||||
RDCLOG("Failed to capture, frame %u: %s", m_CapturedFrames.back().frameNumber, reasonString);
|
||||
|
||||
m_Failures++;
|
||||
|
||||
@@ -2374,7 +2382,8 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
{
|
||||
ContextData &ctxdata = GetCtxData();
|
||||
|
||||
RenderOverlayText(0.0f, 0.0f, "Failed to capture frame %u: %s", m_FrameCounter, reasonString);
|
||||
RenderOverlayText(0.0f, 0.0f, "Failed to capture frame %u: %s",
|
||||
m_CapturedFrames.back().frameNumber, reasonString);
|
||||
|
||||
// swallow all errors we might have inadvertantly caused. This is
|
||||
// better than letting an error propagate and maybe screw up the
|
||||
@@ -2384,7 +2393,9 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
ClearGLErrors();
|
||||
}
|
||||
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
uint32_t failedFrame = m_CapturedFrames.back().frameNumber;
|
||||
|
||||
m_CapturedFrames.back().frameNumber = m_AppControlledCapture ? ~0U : m_FrameCounter;
|
||||
|
||||
CleanupCapture();
|
||||
|
||||
@@ -2410,7 +2421,7 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
|
||||
FreeCaptureData();
|
||||
|
||||
m_FailedFrame = m_FrameCounter;
|
||||
m_FailedFrame = failedFrame;
|
||||
m_FailedReason = reason;
|
||||
|
||||
m_State = CaptureState::BackgroundCapturing;
|
||||
@@ -2494,6 +2505,7 @@ void WrappedOpenGL::FirstFrame(void *ctx, void *wndHandle)
|
||||
RenderDoc::Inst().StartFrameCapture(ctx, NULL);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2555,16 +2567,45 @@ RenderDoc::FramePixels *WrappedOpenGL::SaveBackbufferImage()
|
||||
return fp;
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedOpenGL::Serialise_Present(SerialiserType &ser)
|
||||
{
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading() && IsLoading(m_State))
|
||||
{
|
||||
AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
|
||||
GLuint col = 0;
|
||||
GL.glGetNamedFramebufferAttachmentParameterivEXT(m_CurrentDefaultFBO, eGL_COLOR_ATTACHMENT0,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||
(GLint *)&col);
|
||||
|
||||
draw.copyDestination =
|
||||
GetResourceManager()->GetOriginalID(GetResourceManager()->GetID(TextureRes(GetCtx(), col)));
|
||||
|
||||
draw.name =
|
||||
StringFormat::Fmt("%s(%s)", ToStr(gl_CurChunk).c_str(), ToStr(draw.copyDestination).c_str());
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
AddDrawcall(draw, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedOpenGL::Serialise_CaptureScope(SerialiserType &ser)
|
||||
{
|
||||
SERIALISE_ELEMENT(m_FrameCounter);
|
||||
SERIALISE_ELEMENT_LOCAL(frameNumber, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
m_FrameRecord.frameInfo.frameNumber = m_FrameCounter;
|
||||
m_FrameRecord.frameInfo.frameNumber = frameNumber;
|
||||
RDCEraseEl(m_FrameRecord.frameInfo.stats);
|
||||
}
|
||||
|
||||
@@ -3190,12 +3231,19 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
|
||||
}
|
||||
else if(system == SystemChunk::CaptureEnd)
|
||||
{
|
||||
if(IsLoading(m_State))
|
||||
bool lastSwap =
|
||||
m_LastChunk == GLChunk::SwapBuffers || m_LastChunk == GLChunk::wglSwapBuffers ||
|
||||
m_LastChunk == GLChunk::glXSwapBuffers || m_LastChunk == GLChunk::CGLFlushDrawable ||
|
||||
m_LastChunk == GLChunk::eglSwapBuffers || m_LastChunk == GLChunk::eglPostSubBufferNV ||
|
||||
m_LastChunk == GLChunk::eglSwapBuffersWithDamageEXT ||
|
||||
m_LastChunk == GLChunk::eglSwapBuffersWithDamageKHR;
|
||||
|
||||
if(IsLoading(m_State) && !lastSwap)
|
||||
{
|
||||
AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
draw.name = "SwapBuffers()";
|
||||
draw.name = "End of Capture";
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
GLuint col = 0;
|
||||
@@ -4386,6 +4434,16 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
|
||||
case GLChunk::glReleaseKeyedMutexWin32EXT:
|
||||
return Serialise_glReleaseKeyedMutexWin32EXT(ser, 0, 0);
|
||||
|
||||
case GLChunk::SwapBuffers:
|
||||
case GLChunk::wglSwapBuffers:
|
||||
case GLChunk::glXSwapBuffers:
|
||||
case GLChunk::CGLFlushDrawable:
|
||||
case GLChunk::eglSwapBuffers:
|
||||
case GLChunk::eglPostSubBufferNV:
|
||||
case GLChunk::eglSwapBuffersWithDamageEXT:
|
||||
case GLChunk::eglSwapBuffersWithDamageKHR:
|
||||
return Serialise_Present(ser);
|
||||
|
||||
// these functions are not currently serialised - they do nothing on replay and are not
|
||||
// serialised for information (it would be harmless and perhaps useful for the user to see
|
||||
// where and how they're called).
|
||||
@@ -4854,6 +4912,7 @@ ReplayStatus WrappedOpenGL::ContextReplayLog(CaptureState readType, uint32_t sta
|
||||
if((SystemChunk)chunktype == SystemChunk::CaptureEnd)
|
||||
break;
|
||||
|
||||
m_LastChunk = chunktype;
|
||||
m_CurEventID++;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ private:
|
||||
|
||||
// internals
|
||||
CaptureState m_State;
|
||||
bool m_AppControlledCapture;
|
||||
bool m_AppControlledCapture = false;
|
||||
|
||||
bool m_MarkedActive = false;
|
||||
|
||||
@@ -182,7 +182,7 @@ private:
|
||||
void AddResourceCurChunk(ResourceId id);
|
||||
void AddResourceInitChunk(GLResource res);
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
uint32_t m_FrameCounter = 0;
|
||||
uint32_t m_NoCtxFrames;
|
||||
uint32_t m_FailedFrame;
|
||||
CaptureFailReason m_FailedReason;
|
||||
@@ -240,6 +240,7 @@ private:
|
||||
uint32_t m_CurEventID, m_CurDrawcallID;
|
||||
uint32_t m_FirstEventID;
|
||||
uint32_t m_LastEventID;
|
||||
GLChunk m_LastChunk;
|
||||
|
||||
ReplayStatus m_FailedReplayStatus = ReplayStatus::APIReplayFailed;
|
||||
|
||||
@@ -288,6 +289,9 @@ private:
|
||||
void AddDrawcall(const DrawcallDescription &d, bool hasEvents);
|
||||
void AddEvent();
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_Present(SerialiserType &ser);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_CaptureScope(SerialiserType &ser);
|
||||
|
||||
|
||||
@@ -45,6 +45,15 @@ rdcstr DoStringise(const GLChunk &el)
|
||||
|
||||
STRINGISE_ENUM_CLASS_NAMED(CoherentMapWrite, "Internal: Coherent Mapped Memory Write");
|
||||
|
||||
STRINGISE_ENUM_CLASS(SwapBuffers);
|
||||
STRINGISE_ENUM_CLASS(wglSwapBuffers);
|
||||
STRINGISE_ENUM_CLASS(glXSwapBuffers);
|
||||
STRINGISE_ENUM_CLASS(CGLFlushDrawable);
|
||||
STRINGISE_ENUM_CLASS(eglSwapBuffers);
|
||||
STRINGISE_ENUM_CLASS(eglPostSubBufferNV);
|
||||
STRINGISE_ENUM_CLASS(eglSwapBuffersWithDamageEXT);
|
||||
STRINGISE_ENUM_CLASS(eglSwapBuffersWithDamageKHR);
|
||||
|
||||
// re-use list of GL functions as chunks. Many of these will be aliased. This may not appear in the
|
||||
// same order as the definition, but that's OK.
|
||||
#define StringiseFunction(function, alias) STRINGISE_ENUM_CLASS_NAMED(alias, STRINGIZE(alias));
|
||||
|
||||
@@ -444,6 +444,8 @@ HOOK_EXPORT void glXSwapBuffers_renderdoc_hooked(Display *dpy, GLXDrawable drawa
|
||||
glxhook.UpdateWindowSize(data, dpy, drawable);
|
||||
}
|
||||
|
||||
gl_CurChunk = GLChunk::glXSwapBuffers;
|
||||
|
||||
glxhook.driver.SwapBuffers(WindowingSystem::Xlib, (void *)drawable);
|
||||
|
||||
GLX.glXSwapBuffers(dpy, drawable);
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
std::set<HGLRC> contexts;
|
||||
|
||||
void RefreshWindowParameters(const GLWindowingData &data);
|
||||
void ProcessSwapBuffers(HDC dc);
|
||||
void ProcessSwapBuffers(GLChunk src, HDC dc);
|
||||
void PopulateFromContext(HDC dc, HGLRC rc);
|
||||
GLInitParams GetInitParamsForDC(HDC dc);
|
||||
} wglhook;
|
||||
@@ -161,7 +161,7 @@ void WGLHook::RefreshWindowParameters(const GLWindowingData &data)
|
||||
}
|
||||
}
|
||||
|
||||
void WGLHook::ProcessSwapBuffers(HDC dc)
|
||||
void WGLHook::ProcessSwapBuffers(GLChunk src, HDC dc)
|
||||
{
|
||||
if(eglDisabled)
|
||||
return;
|
||||
@@ -179,6 +179,8 @@ void WGLHook::ProcessSwapBuffers(HDC dc)
|
||||
|
||||
RefreshWindowParameters(data);
|
||||
|
||||
gl_CurChunk = src;
|
||||
|
||||
{
|
||||
SCOPED_LOCK(glLock);
|
||||
driver.SwapBuffers(WindowingSystem::Win32, w);
|
||||
@@ -448,7 +450,7 @@ static BOOL WINAPI SwapBuffers_hooked(HDC dc)
|
||||
{
|
||||
SCOPED_LOCK(glLock);
|
||||
|
||||
wglhook.ProcessSwapBuffers(dc);
|
||||
wglhook.ProcessSwapBuffers(GLChunk::SwapBuffers, dc);
|
||||
|
||||
wglhook.swapRecurse = true;
|
||||
BOOL ret = WGL.SwapBuffers(dc);
|
||||
@@ -461,7 +463,7 @@ static BOOL WINAPI wglSwapBuffers_hooked(HDC dc)
|
||||
{
|
||||
SCOPED_LOCK(glLock);
|
||||
|
||||
wglhook.ProcessSwapBuffers(dc);
|
||||
wglhook.ProcessSwapBuffers(GLChunk::wglSwapBuffers, dc);
|
||||
|
||||
wglhook.swapRecurse = true;
|
||||
BOOL ret = WGL.wglSwapBuffers(dc);
|
||||
@@ -474,7 +476,7 @@ static BOOL WINAPI wglSwapLayerBuffers_hooked(HDC dc, UINT planes)
|
||||
{
|
||||
SCOPED_LOCK(glLock);
|
||||
|
||||
wglhook.ProcessSwapBuffers(dc);
|
||||
wglhook.ProcessSwapBuffers(GLChunk::wglSwapBuffers, dc);
|
||||
|
||||
wglhook.swapRecurse = true;
|
||||
BOOL ret = WGL.wglSwapLayerBuffers(dc, planes);
|
||||
@@ -488,7 +490,7 @@ static BOOL WINAPI wglSwapMultipleBuffers_hooked(UINT numSwaps, CONST WGLSWAP *p
|
||||
SCOPED_LOCK(glLock);
|
||||
|
||||
for(UINT i = 0; pSwaps && i < numSwaps; i++)
|
||||
wglhook.ProcessSwapBuffers(pSwaps[i].hdc);
|
||||
wglhook.ProcessSwapBuffers(GLChunk::wglSwapBuffers, pSwaps[i].hdc);
|
||||
|
||||
wglhook.swapRecurse = true;
|
||||
BOOL ret = WGL.wglSwapMultipleBuffers(numSwaps, pSwaps);
|
||||
|
||||
@@ -293,6 +293,11 @@ void WrappedOpenGL::HandleVRFrameMarkers(const GLchar *buf, GLsizei length)
|
||||
{
|
||||
if(strstr(buf, "vr-marker,frame_end,type,application") != NULL)
|
||||
{
|
||||
PUSH_CURRENT_CHUNK;
|
||||
|
||||
// don't serialise this present as a separate chunk
|
||||
gl_CurChunk = GLChunk::Max;
|
||||
|
||||
SwapBuffers(WindowingSystem::Headless, (void *)m_ActiveContexts[Threading::GetCurrentID()].wnd);
|
||||
m_UsesVRMarkers = true;
|
||||
|
||||
|
||||
@@ -590,6 +590,7 @@ enum class VulkanChunk : uint32_t
|
||||
vkGetSemaphoreCounterValueKHR,
|
||||
vkWaitSemaphoresKHR,
|
||||
vkSignalSemaphoreKHR,
|
||||
vkQueuePresentKHR,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
||||
@@ -116,10 +116,6 @@ WrappedVulkan::WrappedVulkan() : m_RenderState(this, &m_CreationInfo)
|
||||
|
||||
m_Replay.SetDriver(this);
|
||||
|
||||
m_FrameCounter = 0;
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
|
||||
threadSerialiserTLSSlot = Threading::AllocateTLSSlot();
|
||||
tempMemoryTLSSlot = Threading::AllocateTLSSlot();
|
||||
debugMessageSinkTLSSlot = Threading::AllocateTLSSlot();
|
||||
@@ -1334,13 +1330,13 @@ VkResult WrappedVulkan::GetProvidedInstanceExtensionProperties(uint32_t *pProper
|
||||
template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_CaptureScope(SerialiserType &ser)
|
||||
{
|
||||
SERIALISE_ELEMENT(m_FrameCounter);
|
||||
SERIALISE_ELEMENT_LOCAL(frameNumber, m_CapturedFrames.back().frameNumber);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
m_FrameRecord.frameInfo.frameNumber = m_FrameCounter;
|
||||
m_FrameRecord.frameInfo.frameNumber = frameNumber;
|
||||
RDCEraseEl(m_FrameRecord.frameInfo.stats);
|
||||
}
|
||||
|
||||
@@ -1366,6 +1362,7 @@ void WrappedVulkan::FirstFrame()
|
||||
RenderDoc::Inst().StartFrameCapture(LayerDisp(m_Instance), NULL);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1481,10 +1478,8 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd)
|
||||
|
||||
m_SubmitCounter = 0;
|
||||
|
||||
m_FrameCounter = RDCMAX((uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FrameDescription frame;
|
||||
frame.frameNumber = m_FrameCounter;
|
||||
frame.frameNumber = m_AppControlledCapture ? ~0U : m_FrameCounter;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
@@ -1566,7 +1561,7 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd)
|
||||
(*it)->memSize, eFrameRef_ReadBeforeWrite);
|
||||
}
|
||||
|
||||
RDCLOG("Starting capture, frame %u", m_FrameCounter);
|
||||
RDCLOG("Starting capture, frame %u", m_CapturedFrames.back().frameNumber);
|
||||
}
|
||||
|
||||
bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
@@ -1592,7 +1587,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
|
||||
}
|
||||
}
|
||||
|
||||
RDCLOG("Finished capture, Frame %u", m_FrameCounter);
|
||||
RDCLOG("Finished capture, Frame %u", m_CapturedFrames.back().frameNumber);
|
||||
|
||||
VkImage backbuffer = VK_NULL_HANDLE;
|
||||
VkResourceRecord *swaprecord = NULL;
|
||||
@@ -2029,6 +2024,7 @@ void WrappedVulkan::Present(void *dev, void *wnd)
|
||||
bool activeWindow = wnd == NULL || RenderDoc::Inst().IsActiveWindow(dev, wnd);
|
||||
|
||||
RenderDoc::Inst().AddActiveDriver(RDCDriver::Vulkan, true);
|
||||
|
||||
if(!activeWindow)
|
||||
return;
|
||||
|
||||
@@ -2040,6 +2036,7 @@ void WrappedVulkan::Present(void *dev, void *wnd)
|
||||
RenderDoc::Inst().StartFrameCapture(dev, wnd);
|
||||
|
||||
m_AppControlledCapture = false;
|
||||
m_CapturedFrames.back().frameNumber = m_FrameCounter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2365,6 +2362,8 @@ ReplayStatus WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t sta
|
||||
if(IsActiveReplaying(m_State) && startEventID == endEventID)
|
||||
break;
|
||||
|
||||
m_LastChunk = chunktype;
|
||||
|
||||
// increment root event ID either if we didn't just replay a cmd
|
||||
// buffer event, OR if we are doing a frame sub-section replay,
|
||||
// in which case it's up to the calling code to make sure we only
|
||||
@@ -2992,6 +2991,9 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
|
||||
std::vector<ImgRefsPair> data;
|
||||
return GetResourceManager()->Serialise_ImageRefs(ser, data);
|
||||
}
|
||||
case VulkanChunk::vkQueuePresentKHR:
|
||||
return Serialise_vkQueuePresentKHR(ser, VK_NULL_HANDLE, NULL);
|
||||
|
||||
default:
|
||||
{
|
||||
SystemChunk system = (SystemChunk)chunk;
|
||||
@@ -3024,15 +3026,18 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsLoading(m_State))
|
||||
if(PresentedImage != ResourceId())
|
||||
m_LastPresentedImage = PresentedImage;
|
||||
|
||||
if(IsLoading(m_State) && m_LastChunk != VulkanChunk::vkQueuePresentKHR)
|
||||
{
|
||||
AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
draw.name = "vkQueuePresentKHR()";
|
||||
draw.name = "End of Capture";
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
draw.copyDestination = PresentedImage;
|
||||
draw.copyDestination = m_LastPresentedImage;
|
||||
|
||||
AddDrawcall(draw, true);
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ private:
|
||||
void AddDebugMessage(MessageCategory c, MessageSeverity sv, MessageSource src, std::string d);
|
||||
|
||||
CaptureState m_State;
|
||||
bool m_AppControlledCapture;
|
||||
bool m_AppControlledCapture = false;
|
||||
|
||||
bool m_MarkedActive = false;
|
||||
uint32_t m_SubmitCounter = 0;
|
||||
@@ -350,7 +350,7 @@ private:
|
||||
|
||||
std::vector<WindowingSystem> m_SupportedWindowSystems;
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
uint32_t m_FrameCounter = 0;
|
||||
|
||||
std::vector<FrameDescription> m_CapturedFrames;
|
||||
FrameRecord m_FrameRecord;
|
||||
@@ -861,6 +861,9 @@ private:
|
||||
SDChunkMetaData m_ChunkMetadata;
|
||||
uint32_t m_RootEventID, m_RootDrawcallID;
|
||||
uint32_t m_FirstEventID, m_LastEventID;
|
||||
VulkanChunk m_LastChunk;
|
||||
|
||||
ResourceId m_LastPresentedImage;
|
||||
|
||||
ReplayStatus m_FailedReplayStatus = ReplayStatus::APIReplayFailed;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
template <>
|
||||
rdcstr DoStringise(const VulkanChunk &el)
|
||||
{
|
||||
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1139, "Chunks changed without updating names");
|
||||
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1140, "Chunks changed without updating names");
|
||||
|
||||
BEGIN_ENUM_STRINGISE(VulkanChunk)
|
||||
{
|
||||
@@ -171,6 +171,7 @@ rdcstr DoStringise(const VulkanChunk &el)
|
||||
STRINGISE_ENUM_CLASS(vkGetSemaphoreCounterValueKHR);
|
||||
STRINGISE_ENUM_CLASS(vkWaitSemaphoresKHR);
|
||||
STRINGISE_ENUM_CLASS(vkSignalSemaphoreKHR);
|
||||
STRINGISE_ENUM_CLASS(vkQueuePresentKHR);
|
||||
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
|
||||
}
|
||||
END_ENUM_STRINGISE()
|
||||
|
||||
@@ -670,6 +670,49 @@ VkResult WrappedVulkan::vkCreateSwapchainKHR(VkDevice device,
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_vkQueuePresentKHR(SerialiserType &ser, VkQueue queue,
|
||||
const VkPresentInfoKHR *pPresentInfo)
|
||||
{
|
||||
SERIALISE_ELEMENT(queue);
|
||||
SERIALISE_ELEMENT_LOCAL(PresentInfo, *pPresentInfo);
|
||||
|
||||
ResourceId PresentedImage;
|
||||
|
||||
if(ser.IsWriting())
|
||||
{
|
||||
VkResourceRecord *swaprecord = GetRecord(pPresentInfo->pSwapchains[0]);
|
||||
|
||||
SwapchainInfo &swapInfo = *swaprecord->swapInfo;
|
||||
|
||||
PresentedImage = GetResID(swapInfo.images[pPresentInfo->pImageIndices[0]].im);
|
||||
}
|
||||
|
||||
// we don't have all the information we need about swapchains on replay to get the presented image
|
||||
// just from the PresentInfo struct, so we hide it away here
|
||||
SERIALISE_ELEMENT(PresentedImage).Hidden();
|
||||
|
||||
Serialise_DebugMessages(ser);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
AddEvent();
|
||||
|
||||
DrawcallDescription draw;
|
||||
|
||||
draw.name = StringFormat::Fmt("vkQueuePresentKHR(%s)", ToStr(PresentedImage).c_str());
|
||||
draw.flags |= DrawFlags::Present;
|
||||
|
||||
m_LastPresentedImage = draw.copyDestination = PresentedImage;
|
||||
|
||||
AddDrawcall(draw, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VkResult WrappedVulkan::vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
|
||||
{
|
||||
AdvanceFrame();
|
||||
@@ -831,7 +874,18 @@ VkResult WrappedVulkan::vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR
|
||||
}
|
||||
}
|
||||
|
||||
VkResult vkr = ObjDisp(queue)->QueuePresentKHR(Unwrap(queue), &unwrappedInfo);
|
||||
VkResult vkr;
|
||||
SERIALISE_TIME_CALL(vkr = ObjDisp(queue)->QueuePresentKHR(Unwrap(queue), &unwrappedInfo));
|
||||
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkQueuePresentKHR);
|
||||
Serialise_vkQueuePresentKHR(ser, queue, pPresentInfo);
|
||||
|
||||
m_FrameCaptureRecord->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
Present(LayerDisp(m_Instance), swapInfo.wndHandle);
|
||||
|
||||
@@ -1130,3 +1184,6 @@ INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateSwapchainKHR, VkDevice device,
|
||||
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkGetSwapchainImagesKHR, VkDevice device,
|
||||
VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
|
||||
VkImage *pSwapchainImages);
|
||||
|
||||
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkQueuePresentKHR, VkQueue queue,
|
||||
const VkPresentInfoKHR *pPresentInfo);
|
||||
|
||||
@@ -172,7 +172,7 @@ struct GraphicsTest
|
||||
|
||||
bool FrameLimit();
|
||||
|
||||
int curFrame = 0;
|
||||
int curFrame = -1;
|
||||
|
||||
const char *screenTitle = "RenderDoc test program";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user