예제 #1
0
void WrappedID3D11DeviceContext::ReplayLog(LogState readType, uint32_t startEventID, uint32_t endEventID, bool partial)
{
	m_State = readType;

	m_DoStateVerify = true;

	D3D11ChunkType header = (D3D11ChunkType)m_pSerialiser->PushContext(NULL, 1, false);
	RDCASSERT(header == CONTEXT_CAPTURE_HEADER);

	ResourceId id;
	m_pSerialiser->Serialise("context", id);

	WrappedID3D11DeviceContext *context = (WrappedID3D11DeviceContext *)m_pDevice->GetResourceManager()->GetLiveResource(id);
	
	RDCASSERT(WrappedID3D11DeviceContext::IsAlloc(context) && context == this);

	Serialise_BeginCaptureFrame(!partial);

	m_pSerialiser->PopContext(NULL, header);

	m_CurEvents.clear();
	
	if(m_State == EXECUTING)
	{
		FetchAPIEvent ev = GetEvent(startEventID);
		m_CurEventID = ev.eventID;
		m_pSerialiser->SetOffset(ev.fileOffset);
	}
	else if(m_State == READING)
	{
		m_CurEventID = 1;
	}

	if(m_State == EXECUTING)
	{
		ClearMaps();
		for(size_t i=0; i < m_pDevice->GetNumDeferredContexts(); i++)
		{
			WrappedID3D11DeviceContext *defcontext = m_pDevice->GetDeferredContext(i);
			defcontext->ClearMaps();
		}
	}

	m_pDevice->GetResourceManager()->MarkInFrame(true);

	uint64_t startOffset = m_pSerialiser->GetOffset();

	while(1)
	{
		if(m_State == EXECUTING && m_CurEventID > endEventID)
		{
			// we can just break out if we've done all the events desired.
			break;
		}

		uint64_t offset = m_pSerialiser->GetOffset();

		D3D11ChunkType chunktype = (D3D11ChunkType)m_pSerialiser->PushContext(NULL, 1, false);

		ProcessChunk(offset, chunktype, false);
		
		RenderDoc::Inst().SetProgress(FrameEventsRead, float(offset - startOffset)/float(m_pSerialiser->GetSize()));
		
		// for now just abort after capture scope. Really we'd need to support multiple frames
		// but for now this will do.
		if(chunktype == CONTEXT_CAPTURE_FOOTER)
			break;
		
		m_CurEventID++;
	}

	if(m_State == READING)
	{
		m_pDevice->GetFrameRecord().back().drawcallList = m_ParentDrawcall.Bake();
		m_pDevice->GetFrameRecord().back().frameInfo.debugMessages = m_pDevice->GetDebugMessages();

		int initialSkips = 0;

		for(auto it=WrappedID3D11Buffer::m_BufferList.begin(); it != WrappedID3D11Buffer::m_BufferList.end(); ++it)
			m_ResourceUses[it->first];

		for(auto it=WrappedID3D11Texture1D::m_TextureList.begin(); it != WrappedID3D11Texture1D::m_TextureList.end(); ++it)
			m_ResourceUses[it->first];
		for(auto it=WrappedID3D11Texture2D::m_TextureList.begin(); it != WrappedID3D11Texture2D::m_TextureList.end(); ++it)
			m_ResourceUses[it->first];
		for(auto it=WrappedID3D11Texture3D::m_TextureList.begin(); it != WrappedID3D11Texture3D::m_TextureList.end(); ++it)
			m_ResourceUses[it->first];
		
		// it's easier to remove duplicate usages here than check it as we go.
		// this means if textures are bound in multiple places in the same draw
		// we don't have duplicate uses
		for(auto it = m_ResourceUses.begin(); it != m_ResourceUses.end(); ++it)
		{
			vector<EventUsage> &v = it->second;
			std::sort(v.begin(), v.end());
			v.erase( std::unique(v.begin(), v.end()), v.end() );
			
#if 0
			ResourceId resid = m_pDevice->GetResourceManager()->GetOriginalID(it->first);
			
			if(m_pDevice->GetResourceManager()->GetInitialContents(resid).resource == NULL)
				continue;
			
			// code disabled for now as skipping these initial states
			// doesn't seem to produce any measurable improvement in any case
			// I've checked
			RDCDEBUG("Resource %llu", resid);
			if(v.empty())
			{
				RDCDEBUG("Never used!");
				initialSkips++;
			}
			else
			{
				bool written = false;

				for(auto usit = v.begin(); usit != v.end(); ++usit)
				{
					ResourceUsage u = usit->usage;

					if(u == eUsage_SO ||
						(u >= eUsage_VS_RWResource && u <= eUsage_CS_RWResource) ||
						u == eUsage_DepthStencilTarget || u == eUsage_ColourTarget)
					{
						written = true;
						break;
					}
				}

				if(written)
				{
					RDCDEBUG("Written in frame - needs initial state");
				}
				else
				{
					RDCDEBUG("Never written to in the frame");
					initialSkips++;
				}
			}
#endif
		}

		//RDCDEBUG("Can skip %d initial states.", initialSkips);
	}

	m_pDevice->GetResourceManager()->MarkInFrame(false);

	m_State = READING;

	m_DoStateVerify = false;
}
예제 #2
0
void WrappedID3D11DeviceContext::ProcessChunk(uint64_t offset, D3D11ChunkType chunk, bool forceExecute)
{
	if(chunk < FIRST_CONTEXT_CHUNK && !forceExecute)
	{
		if(m_State == READING)
		{
			m_pDevice->GetResourceManager()->MarkInFrame(false);

			m_pDevice->ProcessChunk(offset, chunk);
			m_pSerialiser->PopContext(NULL, chunk);

			m_pDevice->GetResourceManager()->MarkInFrame(true);
		}
		else if(m_State == EXECUTING)
		{
			m_pSerialiser->SkipCurrentChunk();
			m_pSerialiser->PopContext(NULL, chunk);
		}
		return;
	}

	m_CurChunkOffset = offset;

	RDCASSERT(GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE);

	uint64_t cOffs = m_pSerialiser->GetOffset();

	ResourceId ctxId;
	m_pSerialiser->Serialise("context", ctxId);

	WrappedID3D11DeviceContext *context = (WrappedID3D11DeviceContext *)m_pDevice->GetResourceManager()->GetLiveResource(ctxId);

	if(m_FakeContext != ResourceId())
	{
		if(m_FakeContext == ctxId)
			context = this;
		else
		{
			m_pSerialiser->SetOffset(cOffs);
			m_pSerialiser->SkipCurrentChunk();
			m_pSerialiser->PopContext(NULL, chunk);
			return;
		}
	}
	
	RDCASSERT(WrappedID3D11DeviceContext::IsAlloc(context));
	
	LogState state = context->m_State;

	if(forceExecute)
		context->m_State = EXECUTING;
	else
		context->m_State = m_State;

	m_AddedDrawcall = false;

	switch(chunk)
	{
	case SET_INPUT_LAYOUT:
		context->Serialise_IASetInputLayout(0x0);
		break;
	case SET_VBUFFER:
		context->Serialise_IASetVertexBuffers(0, 0, 0x0, 0x0, 0x0);
		break;
	case SET_IBUFFER:
		context->Serialise_IASetIndexBuffer(0, DXGI_FORMAT_UNKNOWN, 0);
		break;
	case SET_TOPOLOGY:
		context->Serialise_IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED);
		break;

	case SET_VS_CBUFFERS:
		context->Serialise_VSSetConstantBuffers(0, 0, 0x0);
		break;
	case SET_VS_RESOURCES:
		context->Serialise_VSSetShaderResources(0, 0, 0x0);
		break;
	case SET_VS_SAMPLERS:
		context->Serialise_VSSetSamplers(0, 0, 0x0);
		break;
	case SET_VS:
		context->Serialise_VSSetShader(0x0, 0x0, 0);
		break;

	case SET_HS_CBUFFERS:
		context->Serialise_HSSetConstantBuffers(0, 0, 0x0);
		break;
	case SET_HS_RESOURCES:
		context->Serialise_HSSetShaderResources(0, 0, 0x0);
		break;
	case SET_HS_SAMPLERS:
		context->Serialise_HSSetSamplers(0, 0, 0x0);
		break;
	case SET_HS:
		context->Serialise_HSSetShader(0x0, 0x0, 0);
		break;

	case SET_DS_CBUFFERS:
		context->Serialise_DSSetConstantBuffers(0, 0, 0x0);
		break;
	case SET_DS_RESOURCES:
		context->Serialise_DSSetShaderResources(0, 0, 0x0);
		break;
	case SET_DS_SAMPLERS:
		context->Serialise_DSSetSamplers(0, 0, 0x0);
		break;
	case SET_DS:
		context->Serialise_DSSetShader(0x0, 0x0, 0);
		break;
		
	case SET_GS_CBUFFERS:
		context->Serialise_GSSetConstantBuffers(0, 0, 0x0);
		break;
	case SET_GS_RESOURCES:
		context->Serialise_GSSetShaderResources(0, 0, 0x0);
		break;
	case SET_GS_SAMPLERS:
		context->Serialise_GSSetSamplers(0, 0, 0x0);
		break;
	case SET_GS:
		context->Serialise_GSSetShader(0x0, 0x0, 0);
		break;

	case SET_SO_TARGETS:
		context->Serialise_SOSetTargets(0, 0x0, 0x0);
		break;
		
	case SET_PS_CBUFFERS:
		context->Serialise_PSSetConstantBuffers(0, 0, 0x0);
		break;
	case SET_PS_RESOURCES:
		context->Serialise_PSSetShaderResources(0, 0, 0x0);
		break;
	case SET_PS_SAMPLERS:
		context->Serialise_PSSetSamplers(0, 0, 0x0);
		break;
	case SET_PS:
		context->Serialise_PSSetShader(0x0, 0x0, 0);
		break;

	case SET_CS_CBUFFERS:
		context->Serialise_CSSetConstantBuffers(0, 0, 0x0);
		break;
	case SET_CS_RESOURCES:
		context->Serialise_CSSetShaderResources(0, 0, 0x0);
		break;
	case SET_CS_UAVS:
		context->Serialise_CSSetUnorderedAccessViews(0, 0, 0x0, 0x0);
		break;
	case SET_CS_SAMPLERS:
		context->Serialise_CSSetSamplers(0, 0, 0x0);
		break;
	case SET_CS:
		context->Serialise_CSSetShader(0x0, 0x0, 0);
		break;

	case SET_VIEWPORTS:
		context->Serialise_RSSetViewports(0, 0x0);
		break;
	case SET_SCISSORS:
		context->Serialise_RSSetScissorRects(0, 0x0);
		break;
	case SET_RASTER:
		context->Serialise_RSSetState(0x0);
		break;

	case SET_RTARGET:
		context->Serialise_OMSetRenderTargets(0, 0x0, 0x0);
		break;
	case SET_RTARGET_AND_UAVS:
		context->Serialise_OMSetRenderTargetsAndUnorderedAccessViews(0, 0x0, 0x0, 0, 0, 0x0, 0x0);
		break;
	case SET_BLEND:
		context->Serialise_OMSetBlendState(0x0, (FLOAT*)0x0, 0);
		break;
	case SET_DEPTHSTENCIL:
		context->Serialise_OMSetDepthStencilState(0x0, 0);
		break;
		
	case DRAW_INDEXED_INST:
		context->Serialise_DrawIndexedInstanced(0, 0, 0, 0, 0);
		break;
	case DRAW_INST:
		context->Serialise_DrawInstanced(0, 0, 0, 0);
		break;
	case DRAW_INDEXED:
		context->Serialise_DrawIndexed(0, 0, 0);
		break;
	case DRAW:
		context->Serialise_Draw(0, 0);
		break;
	case DRAW_AUTO:
		context->Serialise_DrawAuto();
		break;
	case DRAW_INDEXED_INST_INDIRECT:
		context->Serialise_DrawIndexedInstancedIndirect(0x0, 0);
		break;
	case DRAW_INST_INDIRECT:
		context->Serialise_DrawInstancedIndirect(0x0, 0);
		break;

	case MAP:
		context->Serialise_Map(0, 0, (D3D11_MAP)0, 0, 0);
		break;
	case UNMAP:
		context->Serialise_Unmap(0, 0);
		break;
		
	case COPY_SUBRESOURCE_REGION:
		context->Serialise_CopySubresourceRegion(0x0, 0, 0, 0, 0, 0x0, 0, 0x0);
		break;
	case COPY_RESOURCE:
		context->Serialise_CopyResource(0x0, 0x0);
		break;
	case UPDATE_SUBRESOURCE:
		context->Serialise_UpdateSubresource(0x0, 0, 0x0, 0x0, 0, 0);
		break;
	case COPY_STRUCTURE_COUNT:
		context->Serialise_CopyStructureCount(0x0, 0, 0x0);
		break;
	case RESOLVE_SUBRESOURCE:
		context->Serialise_ResolveSubresource(0x0, 0, 0x0, 0, DXGI_FORMAT_UNKNOWN);
		break;
	case GENERATE_MIPS:
		context->Serialise_GenerateMips(0x0);
		break;

	case CLEAR_DSV:
		context->Serialise_ClearDepthStencilView(0x0, 0, 0.0f, 0);
		break;
	case CLEAR_RTV:
		context->Serialise_ClearRenderTargetView(0x0, (FLOAT*)0x0);
		break;
	case CLEAR_UAV_INT:
		context->Serialise_ClearUnorderedAccessViewUint(0x0, (UINT*)0x0);
		break;
	case CLEAR_UAV_FLOAT:
		context->Serialise_ClearUnorderedAccessViewFloat(0x0, (FLOAT*)0x0);
		break;
	case CLEAR_STATE:
		context->Serialise_ClearState();
		break;
		
	case EXECUTE_CMD_LIST:
		context->Serialise_ExecuteCommandList(0x0, 0);
		break;
	case DISPATCH:
		context->Serialise_Dispatch(0, 0, 0);
		break;
	case DISPATCH_INDIRECT:
		context->Serialise_DispatchIndirect(0x0, 0);
		break;
	case FINISH_CMD_LIST:
		context->Serialise_FinishCommandList(0, 0x0);
		break;
	case FLUSH:
		context->Serialise_Flush();
		break;
		
	case SET_PREDICATION:
		context->Serialise_SetPredication(0x0, 0x0);
		break;
	case SET_RESOURCE_MINLOD:
		context->Serialise_SetResourceMinLOD(0x0, 0);
		break;

	case BEGIN:
		context->Serialise_Begin(0x0);
		break;
	case END:
		context->Serialise_End(0x0);
		break;
		
#if defined(INCLUDE_D3D_11_1)
	case COPY_SUBRESOURCE_REGION1:
		context->Serialise_CopySubresourceRegion1(0x0, 0, 0, 0, 0, 0x0, 0, 0x0, 0);
		break;
	case UPDATE_SUBRESOURCE1:
		context->Serialise_UpdateSubresource1(0x0, 0, 0x0, 0x0, 0, 0, 0);
		break;
	case CLEAR_VIEW:
		context->Serialise_ClearView(0x0, 0x0, 0x0, 0);
		break;

	case SET_VS_CBUFFERS1:
		context->Serialise_VSSetConstantBuffers1(0, 0, 0x0, 0x0, 0x0);
		break;
	case SET_HS_CBUFFERS1:
		context->Serialise_HSSetConstantBuffers1(0, 0, 0x0, 0x0, 0x0);
		break;
	case SET_DS_CBUFFERS1:
		context->Serialise_DSSetConstantBuffers1(0, 0, 0x0, 0x0, 0x0);
		break;
	case SET_GS_CBUFFERS1:
		context->Serialise_GSSetConstantBuffers1(0, 0, 0x0, 0x0, 0x0);
		break;
	case SET_PS_CBUFFERS1:
		context->Serialise_PSSetConstantBuffers1(0, 0, 0x0, 0x0, 0x0);
		break;
	case SET_CS_CBUFFERS1:
		context->Serialise_CSSetConstantBuffers1(0, 0, 0x0, 0x0, 0x0);
		break;
#else
	case COPY_SUBRESOURCE_REGION1:
	case UPDATE_SUBRESOURCE1:
	case CLEAR_VIEW:
	case SET_VS_CBUFFERS1:
	case SET_HS_CBUFFERS1:
	case SET_DS_CBUFFERS1:
	case SET_GS_CBUFFERS1:
	case SET_PS_CBUFFERS1:
	case SET_CS_CBUFFERS1:
		RDCERR("Replaying log with D3D11.1 events on a build without D3D11.1 support");
		break;
#endif

	case PUSH_EVENT:
		context->Serialise_PushEvent(0, L"");
		break;
	case SET_MARKER:
		context->Serialise_SetMarker(0, L"");
		break;
	case POP_EVENT:
		context->Serialise_PopEvent();
		break;

	case CONTEXT_CAPTURE_FOOTER:
		{
			bool HasCallstack = false;
			m_pSerialiser->Serialise("HasCallstack", HasCallstack);	

			if(HasCallstack)
			{
				size_t numLevels = 0;
				uint64_t *stack = NULL;

				m_pSerialiser->SerialisePODArray("callstack", stack, numLevels);

				m_pSerialiser->SetCallstack(stack, numLevels);

				SAFE_DELETE_ARRAY(stack);
			}

			if(m_State == READING)
			{
				AddEvent(CONTEXT_CAPTURE_FOOTER, "IDXGISwapChain::Present()");

				FetchDrawcall draw;
				draw.name = "Present()";
				draw.flags |= eDraw_Present;

				AddDrawcall(draw, true);
			}
		}
		break;
	default:
		RDCERR("Unrecognised Chunk type %d", chunk);
		break;
	}

	m_pSerialiser->PopContext(NULL, chunk);
	
	if(context->m_State == READING && chunk == SET_MARKER)
	{
		// no push/pop necessary
	}
	else if(context->m_State == READING && chunk == PUSH_EVENT)
	{
		// push down the drawcallstack to the latest drawcall
		context->m_DrawcallStack.push_back(&context->m_DrawcallStack.back()->children.back());
	}
	else if(context->m_State == READING && chunk == POP_EVENT)
	{
		// refuse to pop off further than the root drawcall (mismatched begin/end events e.g.)
		if(context->m_DrawcallStack.size() > 1)
			context->m_DrawcallStack.pop_back();
	}
	else if(context->m_State == READING)
	{
		if(!m_AddedDrawcall)
			context->AddEvent(chunk, m_pSerialiser->GetDebugStr());
	}

	m_AddedDrawcall = false;
	
	if(forceExecute)
		context->m_State = state;
}
예제 #3
0
void WrappedID3D11DeviceContext::ReplayLog(LogState readType, uint32_t startEventID, uint32_t endEventID, bool partial)
{
	m_State = readType;

	m_DoStateVerify = true;

	D3D11ChunkType header = (D3D11ChunkType)m_pSerialiser->PushContext(NULL, 1, false);
	RDCASSERT(header == CONTEXT_CAPTURE_HEADER);

	ResourceId id;
	m_pSerialiser->Serialise("context", id);

	WrappedID3D11DeviceContext *context = (WrappedID3D11DeviceContext *)m_pDevice->GetResourceManager()->GetLiveResource(id);
	
	RDCASSERT(WrappedID3D11DeviceContext::IsAlloc(context) && context == this);

	Serialise_BeginCaptureFrame(!partial);

	m_pSerialiser->PopContext(NULL, header);

	m_CurEvents.clear();
	
	if(m_State == EXECUTING)
	{
		FetchAPIEvent ev = GetEvent(startEventID);
		m_CurEventID = ev.eventID;
		m_pSerialiser->SetOffset(ev.fileOffset);
	}
	else if(m_State == READING)
	{
		m_CurEventID = 1;
	}

	if(m_State == EXECUTING)
	{
		ClearMaps();
		for(size_t i=0; i < m_pDevice->GetNumDeferredContexts(); i++)
		{
			WrappedID3D11DeviceContext *context = m_pDevice->GetDeferredContext(i);
			context->ClearMaps();
		}
	}

	m_pDevice->GetResourceManager()->MarkInFrame(true);

	while(1)
	{
		if(m_State == EXECUTING && m_CurEventID > endEventID)
		{
			// we can just break out if we've done all the events desired.
			break;
		}

		uint64_t offset = m_pSerialiser->GetOffset();

		D3D11ChunkType context = (D3D11ChunkType)m_pSerialiser->PushContext(NULL, 1, false);

		ProcessChunk(offset, context, false);
		
		RenderDoc::Inst().SetProgress(FileInitialRead, float(offset)/float(m_pSerialiser->GetSize()));
		
		// for now just abort after capture scope. Really we'd need to support multiple frames
		// but for now this will do.
		if(context == CONTEXT_CAPTURE_FOOTER)
			break;
		
		m_CurEventID++;
	}

	if(m_State == READING)
	{
		m_pDevice->GetFrameRecord().back().drawcallList = m_ParentDrawcall.Bake();

		m_ParentDrawcall.children.clear();

		int initialSkips = 0;

		for(auto it=WrappedID3D11Buffer::m_BufferList.begin(); it != WrappedID3D11Buffer::m_BufferList.end(); ++it)
			m_ResourceUses[it->first];

		for(auto it=WrappedID3D11Texture1D::m_TextureList.begin(); it != WrappedID3D11Texture1D::m_TextureList.end(); ++it)
			m_ResourceUses[it->first];
		for(auto it=WrappedID3D11Texture2D::m_TextureList.begin(); it != WrappedID3D11Texture2D::m_TextureList.end(); ++it)
			m_ResourceUses[it->first];
		for(auto it=WrappedID3D11Texture3D::m_TextureList.begin(); it != WrappedID3D11Texture3D::m_TextureList.end(); ++it)
			m_ResourceUses[it->first];

		for(auto it = m_ResourceUses.begin(); it != m_ResourceUses.end(); ++it)
		{
			ResourceId id = m_pDevice->GetResourceManager()->GetOriginalID(it->first);

			if(m_pDevice->GetResourceManager()->GetInitialContents(id) == NULL)
				continue;

			RDCDEBUG("Resource %llu", id);
			if(it->second.empty())
			{
				RDCDEBUG("Never used!");
				initialSkips++;
			}
			else
			{
				bool written = false;

				for(auto usit = it->second.begin(); usit != it->second.end(); ++usit)
				{
					ResourceUsage u = usit->usage;

					if(u == eUsage_SO ||
						u == eUsage_CS_UAV || u == eUsage_PS_UAV ||
						u == eUsage_OM_DSV || u == eUsage_OM_RTV)
					{
						written = true;
						break;
					}
				}

				if(written)
				{
					RDCDEBUG("Written in frame - needs initial state");
				}
				else
				{
					RDCDEBUG("Never written to in the frame");
					initialSkips++;
				}
			}
		}

		RDCDEBUG("Can skip %d initial states.", initialSkips);
	}

	m_pDevice->GetResourceManager()->MarkInFrame(false);

	m_State = READING;

	m_DoStateVerify = false;
}