예제 #1
0
    DspChunk DspRate::ProcessEosChunk(soxr_t soxr, DspChunk& chunk)
    {
        assert(soxr);

        DspChunk output;

        if (!chunk.IsEmpty())
            output = ProcessChunk(soxr, chunk);

        for (;;)
        {
            DspChunk tailChunk(DspFormat::Float, m_channels, m_outputRate, m_outputRate);

            size_t inputDone = 0;
            size_t outputDo = tailChunk.GetFrameCount();
            size_t outputDone = 0;
            soxr_process(soxr, nullptr, 0, &inputDone,
                               tailChunk.GetData(), outputDo, &outputDone);
            tailChunk.ShrinkTail(outputDone);

            DspChunk::MergeChunks(output, tailChunk);

            if (outputDone < outputDo)
                break;
        }

        return output;
    }
예제 #2
0
    void DspRate::Process(DspChunk& chunk)
    {
        soxr_t soxr = GetBackend();

        if (!soxr || chunk.IsEmpty())
            return;

        if (m_state == State::Variable && !m_inStateTransition && m_variableDelay > 0)
        {
            uint64_t inputPosition = llMulDiv(m_variableOutputFrames, m_inputRate, m_outputRate, 0);
            int64_t adjustedFrames = inputPosition + m_variableDelay - m_variableInputFrames;

            REFERENCE_TIME adjustTime = m_adjustTime - FramesToTimeLong(adjustedFrames, m_inputRate);

            double ratio = (double)m_inputRate * 4 / (m_outputRate * (4 + (double)adjustTime / OneSecond));

            // TODO: decrease jitter

            soxr_set_io_ratio(m_soxrv, ratio, m_outputRate / 1000);
        }

        DspChunk output = ProcessChunk(soxr, chunk);

        if (m_state == State::Variable)
        {
            m_variableInputFrames += chunk.GetFrameCount();
            m_variableOutputFrames += output.GetFrameCount();

            // soxr_delay() method is not implemented for variable rate conversion yet,
            // but the delay stays more or less constant and we can calculate it in a roundabout way.
            if (m_variableDelay == 0 && m_variableOutputFrames > 0)
            {
                uint64_t inputPosition = llMulDiv(m_variableOutputFrames, m_inputRate, m_outputRate, 0);
                m_variableDelay = m_variableInputFrames - inputPosition;
            }
        }

        FinishStateTransition(output, chunk, false);

        chunk = std::move(output);
    }
예제 #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 *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;
}
예제 #4
0
void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEventID,
                                          uint32_t endEventID, bool partial)
{
  m_State = readType;

  D3D12ChunkType header = (D3D12ChunkType)m_pSerialiser->PushContext(NULL, NULL, 1, false);
  RDCASSERTEQUAL(header, CONTEXT_CAPTURE_HEADER);

  m_pDevice->Serialise_BeginCaptureFrame(!partial);

  if(readType == READING)
  {
    GetResourceManager()->ApplyInitialContents();

    m_pDevice->ExecuteLists();
    m_pDevice->FlushLists();
  }

  m_pSerialiser->PopContext(header);

  m_Cmd.m_RootEvents.clear();

  if(m_State == EXECUTING)
  {
    FetchAPIEvent ev = GetEvent(startEventID);
    m_Cmd.m_RootEventID = ev.eventID;

    // if not partial, we need to be sure to replay
    // past the command list records, so can't
    // skip to the file offset of the first event
    if(partial)
      m_pSerialiser->SetOffset(ev.fileOffset);

    m_Cmd.m_FirstEventID = startEventID;
    m_Cmd.m_LastEventID = endEventID;
  }
  else if(m_State == READING)
  {
    m_Cmd.m_RootEventID = 1;
    m_Cmd.m_RootDrawcallID = 1;
    m_Cmd.m_FirstEventID = 0;
    m_Cmd.m_LastEventID = ~0U;
  }

  for(;;)
  {
    if(m_State == EXECUTING && m_Cmd.m_RootEventID > endEventID)
    {
      // we can just break out if we've done all the events desired.
      // note that the command list events aren't 'real' and we just blaze through them
      break;
    }

    uint64_t offset = m_pSerialiser->GetOffset();

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

    m_Cmd.m_LastCmdListID = ResourceId();

    ProcessChunk(offset, context);

    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;

    // break out if we were only executing one event
    if(m_State == EXECUTING && startEventID == endEventID)
      break;

    // 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
    // replay inside a command list (if we crossed command list
    // boundaries, the event IDs would no longer match up).
    if(m_Cmd.m_LastCmdListID == ResourceId() || startEventID > 1)
    {
      m_Cmd.m_RootEventID++;

      if(startEventID > 1)
        m_pSerialiser->SetOffset(GetEvent(m_Cmd.m_RootEventID).fileOffset);
    }
    else
    {
      m_Cmd.m_BakedCmdListInfo[m_Cmd.m_LastCmdListID].curEventID++;
    }
  }

  if(m_State == READING)
  {
    struct SortEID
    {
      bool operator()(const FetchAPIEvent &a, const FetchAPIEvent &b)
      {
        return a.eventID < b.eventID;
      }
    };

    std::sort(m_Cmd.m_Events.begin(), m_Cmd.m_Events.end(), SortEID());
  }

  for(int p = 0; p < D3D12CommandData::ePartialNum; p++)
    SAFE_RELEASE(m_Cmd.m_Partial[p].resultPartialCmdList);

  for(auto it = m_Cmd.m_RerecordCmds.begin(); it != m_Cmd.m_RerecordCmds.end(); ++it)
    SAFE_RELEASE(it->second);

  m_Cmd.m_RerecordCmds.clear();

  m_State = READING;
}
예제 #5
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;
}
예제 #6
0
    void DspRate::FinishStateTransition(DspChunk& processedChunk, DspChunk& unprocessedChunk, bool eos)
    {
        if (m_inStateTransition)
        {
            assert(m_state == State::Variable);

            DspChunk::ToFloat(processedChunk);
            DspChunk::ToFloat(unprocessedChunk);

            auto& first = m_transitionChunks.first;
            auto& second = m_transitionChunks.second;

            DspChunk::MergeChunks(first, processedChunk);
            assert(processedChunk.IsEmpty());

            if (m_soxrc)
            {
                // Transitioning from constant rate conversion to variable.
                if (!m_transitionCorrelation.first)
                    m_transitionCorrelation = {true, (size_t)std::round(soxr_delay(m_soxrc))};

                if (m_transitionCorrelation.second > 0)
                {
                    DspChunk::MergeChunks(second, eos ? ProcessEosChunk(m_soxrc, unprocessedChunk) :
                                                        ProcessChunk(m_soxrc, unprocessedChunk));
                }
                else
                {
                    // Nothing to flush from constant rate conversion buffer.
                    m_inStateTransition = false;
                }
            }
            else
            {
                // Transitioning from pass-through to variable rate conversion.
                m_transitionCorrelation = {};
                DspChunk::MergeChunks(second, unprocessedChunk);
            }

            // Cross-fade.
            if (m_inStateTransition)
            {
                const size_t transitionFrames = m_outputRate / 1000; // 1ms

                if (first.GetFrameCount() >= transitionFrames &&
                    second.GetFrameCount() >= m_transitionCorrelation.second + transitionFrames)
                {
                    second.ShrinkHead(second.GetFrameCount() - m_transitionCorrelation.second);
                    Crossfade(first, second, transitionFrames);
                    processedChunk = std::move(first);
                    m_inStateTransition = false;
                }
                else if (eos)
                {
                    processedChunk = std::move(second);
                    m_inStateTransition = false;
                }
            }

            if (!m_inStateTransition)
            {
                m_transitionCorrelation = {};
                m_transitionChunks = {};
                DestroyBackend(m_soxrc);
            }
        }

        unprocessedChunk = {};
    }
예제 #7
0
DWORD ReadHeader(FILE *f, int depth, DWORD max_size)
{
    struct
    {
        DWORD type;
        DWORD size;
    } header;

    DWORD size = 0;

    if (fread(&header, 1, sizeof(header), f) == sizeof(header))
    {
        size = header.size & 0x7FFFFFFF;

        char *chunk_type = lookup(header.type, size);
        indent = depth * 3;
        fprintf(outf, "%s%08X %s [%d]\n", Indent(), header.type, chunk_type, size);
        indent = depth * 3 + 9;

        if (size > 4*1024*1024)
        {
            printf("*ERROR* header is exceedingly big!\n");
        }
        else if (depth > 10)
        {
            printf("*ERROR* nested too deep!\n");
        }
        else if (size + sizeof(header) > max_size)
        {
            printf("*ERROR* structure size exceeds container!\n");
        }
        else
        {
            if (IsNested(header.type))
            {
                long remaining = size;
                while (remaining > 0)
                {
                    DWORD bytes_read = ReadHeader(f, depth + 1, remaining) + sizeof(header);
                    remaining -= bytes_read;
                }
            }
            else
            {
                BYTE *data = new BYTE[size];
                fread(data, size, 1, f);
                ProcessChunk(header.type, data, size);
                delete data;
            }
        }
    }
    else
    {
        if (depth > 0)
        {
            printf("*ERROR* fread failed\n");
        }
    }

    return (size);
}