//-----------------------------------------------------------------------------
/// Handles operations that need to occur before profiling an API call.
/// \param funcId The FuncId corresponding to the API call being traced.
/// \param pWrappedCmdBuf The interface pointer used to invoke the API call.
//-----------------------------------------------------------------------------
void VktFrameProfilerLayer::PreCall(FuncId funcId, VktWrappedCmdBuf* pWrappedCmdBuf)
{
    if (pWrappedCmdBuf->IsProfilingEnabled() && ShouldProfileFunction(funcId))
    {
        osThreadId threadId = osGetCurrentThreadId();
        SampleInfo* pSampleInfo = GetSampleInfoForThread(threadId);

        if (pSampleInfo != nullptr)
        {
            UINT64 nextSampleId = SetNextSampleId(pSampleInfo);

            ProfilerMeasurementId measurementId = {};
            VktUtil::ConstructMeasurementInfo(funcId, nextSampleId, pWrappedCmdBuf, GetParentLayerManager()->GetFrameCount(), pWrappedCmdBuf->FillCount(), measurementId);

            ProfilerResultCode beginResult = pWrappedCmdBuf->BeginCmdMeasurement(&measurementId);

            if (beginResult == PROFILER_SUCCESS)
            {
                pSampleInfo->mSampleId = measurementId.sampleId;
                pSampleInfo->mbBeginSampleSuccessful = true;
            }
            else
            {
                Log(logERROR, "Failed BeginCmdMeasurement. CmdBuf='0x%p' SampleId='%d'\n", pWrappedCmdBuf->AppHandle(), measurementId.sampleId);
            }
        }
        else
        {
            Log(logERROR, "Failed to find or create SampleInfo instance for Thread %d\n", threadId);
        }
    }
}
//-----------------------------------------------------------------------------
/// Handles operations that need to occur before profiling an API call.
/// \param inWrappedInterface The interface pointer used to invoke the API call.
/// \param inFunctionId The FuncId corresponding to the API call being traced.
//-----------------------------------------------------------------------------
void DX12FrameProfilerLayer::PreCall(IUnknown* inWrappedInterface, FuncId inFunctionId)
{
    Wrapped_ID3D12GraphicsCommandListCustom* pWrappedGraphicsCommandListCustom = static_cast<Wrapped_ID3D12GraphicsCommandListCustom*>(inWrappedInterface);

    // Check if we intend to collect GPU time
    if (pWrappedGraphicsCommandListCustom->IsProfilingEnabled() && ShouldProfileFunction(inFunctionId))
    {
        osThreadId threadId = osGetCurrentThreadId();
        SampleInfo* pSampleInfo = GetSampleInfoForThread(threadId);

        if (pSampleInfo != nullptr)
        {
            // Don't let new sampling begin until this sample is finished with a call to EndSample.
            Wrapped_ID3D12CommandList* pCmdList = static_cast<Wrapped_ID3D12CommandList*>(inWrappedInterface);

            // Only some types of CommandLists can be timestamped. Check the type before proceeding.
            if (CommandListSupportsTimestamping(pCmdList) == true)
            {
                UINT64 nextSampleId = SetNextSampleId(pSampleInfo);

                ProfilerMeasurementId measurementId = {};
                ConstructMeasurementInfo(inFunctionId, nextSampleId, pWrappedGraphicsCommandListCustom, measurementId);

                ProfilerResultCode beginResult = pWrappedGraphicsCommandListCustom->BeginCmdMeasurement(&measurementId);

                if (beginResult == PROFILER_SUCCESS)
                {
                    pSampleInfo->mSampleId = measurementId.mSampleId;
                    pSampleInfo->mbBeginSampleSuccessful = true;
                }
                else
                {
                    Log(logERROR, "Failed BeginCmdMeasurement. CmdList='0x%p' SampleId='%d'\n", pWrappedGraphicsCommandListCustom->mRealGraphicsCommandList, measurementId.mSampleId);
                }
            }
        }
        else
        {
            Log(logERROR, "Failed to find or create SampleInfo instance for Thread %d\n", threadId);
        }
    }
}