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:
baldurk
2019-11-21 17:09:01 +00:00
parent cb216441fe
commit 4458ab3205
37 changed files with 454 additions and 147 deletions
+33 -5
View File
@@ -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);
+7 -3
View File
@@ -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();
+6 -1
View File
@@ -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());
+10 -2
View File
@@ -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
View File
@@ -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++;
}
}
+41 -27
View File
@@ -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++;
}
+2 -3
View File
@@ -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);
+25 -19
View File
@@ -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;
+6 -4
View File
@@ -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,
+9 -4
View File
@@ -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
+3
View File
@@ -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;
+1
View File
@@ -827,5 +827,6 @@ enum class D3D12Chunk : uint32_t
List_RSSetShadingRate,
List_RSSetShadingRateImage,
Device_ExternalDXGIResource,
Swapchain_Present,
Max,
};
+69 -16
View File
@@ -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;
+8 -4
View File
@@ -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);
+6 -3
View File
@@ -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;
+2 -1
View File
@@ -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()
-2
View File
@@ -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();
+1 -1
View File
@@ -228,7 +228,7 @@ private:
RefCounter8 m_SoftRefCounter;
bool m_Alive;
uint32_t m_FrameCounter;
uint32_t m_FrameCounter = 0;
};
////////////////////////////////////////////////////////////////////////////
-2
View File
@@ -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();
+1 -1
View File
@@ -258,7 +258,7 @@ private:
RefCounter9 m_SoftRefCounter;
bool m_Alive;
uint32_t m_FrameCounter;
uint32_t m_FrameCounter = 0;
};
////////////////////////////////////////////////////////////////////////////
+2
View File
@@ -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);
}
+8
View File
@@ -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);
}
+9
View File
@@ -2163,6 +2163,15 @@ enum class GLChunk : uint32_t
glBlendEquationARB,
glPrimitiveBoundingBoxARB,
SwapBuffers,
wglSwapBuffers,
glXSwapBuffers,
CGLFlushDrawable,
eglSwapBuffers,
eglPostSubBufferNV,
eglSwapBuffersWithDamageEXT,
eglSwapBuffersWithDamageKHR,
Max,
};
+75 -16
View File
@@ -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++;
}
+6 -2
View File
@@ -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);
+9
View File
@@ -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));
+2
View File
@@ -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);
+8 -6
View File
@@ -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;
+1
View File
@@ -590,6 +590,7 @@ enum class VulkanChunk : uint32_t
vkGetSemaphoreCounterValueKHR,
vkWaitSemaphoresKHR,
vkSignalSemaphoreKHR,
vkQueuePresentKHR,
Max,
};
+19 -14
View File
@@ -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);
}
+5 -2
View File
@@ -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;
+2 -1
View File
@@ -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);
+1 -1
View File
@@ -172,7 +172,7 @@ struct GraphicsTest
bool FrameLimit();
int curFrame = 0;
int curFrame = -1;
const char *screenTitle = "RenderDoc test program";