mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-09 17:17:11 +00:00
Implemented data retrieval from selected NV counters
This commit is contained in:
committed by
Baldur Karlsson
parent
f3cb0e1854
commit
7347a11dff
@@ -348,9 +348,71 @@ void D3D11Replay::FillTimersAMD(uint32_t &eventStartID, uint32_t &sampleIndex,
|
||||
}
|
||||
}
|
||||
|
||||
static void FlushGPU(WrappedID3D11Device *pDevice, WrappedID3D11DeviceContext *pImmediateContext)
|
||||
{
|
||||
ID3D11Query *pAPIQuery = NULL;
|
||||
D3D11_QUERY_DESC queryDesc;
|
||||
queryDesc.Query = D3D11_QUERY_EVENT;
|
||||
queryDesc.MiscFlags = 0;
|
||||
if(FAILED(pDevice->CreateQuery(&queryDesc, &pAPIQuery)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
pImmediateContext->Flush();
|
||||
pImmediateContext->End(pAPIQuery);
|
||||
pImmediateContext->Flush();
|
||||
if(S_OK != (hr = pImmediateContext->GetData(pAPIQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH)))
|
||||
{
|
||||
do
|
||||
{
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
::Sleep(0); // Give up time slice
|
||||
} while(S_OK !=
|
||||
(hr = pImmediateContext->GetData(pAPIQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH)));
|
||||
}
|
||||
|
||||
if(pAPIQuery)
|
||||
pAPIQuery->Release();
|
||||
}
|
||||
|
||||
void D3D11Replay::FillTimersNV(uint32_t &eventStartID, uint32_t &sampleIndex,
|
||||
vector<uint32_t> &eventIDs, const DrawcallDescription &drawnode)
|
||||
{
|
||||
if(drawnode.children.empty())
|
||||
return;
|
||||
|
||||
for(size_t i = 0; i < drawnode.children.size(); i++)
|
||||
{
|
||||
const DrawcallDescription &d = drawnode.children[i];
|
||||
|
||||
FillTimersNV(eventStartID, sampleIndex, eventIDs, drawnode.children[i]);
|
||||
|
||||
if(d.events.empty() || (!(drawnode.children[i].flags & DrawFlags::Drawcall) &&
|
||||
!(drawnode.children[i].flags & DrawFlags::Dispatch)))
|
||||
continue;
|
||||
|
||||
eventIDs.push_back(d.eventId);
|
||||
|
||||
m_pDevice->ReplayLog(eventStartID, d.eventId, eReplay_WithoutDraw);
|
||||
|
||||
FlushGPU(m_pDevice, m_pImmediateContext);
|
||||
|
||||
m_pNVCounters->BeginSample(sampleIndex);
|
||||
|
||||
m_pDevice->ReplayLog(eventStartID, d.eventId, eReplay_OnlyDraw);
|
||||
|
||||
FlushGPU(m_pDevice, m_pImmediateContext);
|
||||
|
||||
m_pNVCounters->EndSample(sampleIndex);
|
||||
|
||||
eventStartID = d.eventId + 1;
|
||||
sampleIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
vector<CounterResult> D3D11Replay::FetchCountersAMD(const vector<GPUCounter> &counters)
|
||||
@@ -398,7 +460,36 @@ vector<CounterResult> D3D11Replay::FetchCountersAMD(const vector<GPUCounter> &co
|
||||
|
||||
vector<CounterResult> D3D11Replay::FetchCountersNV(const vector<GPUCounter> &counters)
|
||||
{
|
||||
const FrameRecord &frameRecord = m_pDevice->GetFrameRecord();
|
||||
const FrameStatistics &frameStats = frameRecord.frameInfo.stats;
|
||||
|
||||
const uint32_t objectsCount = frameStats.draws.calls + frameStats.dispatches.calls + 1;
|
||||
|
||||
vector<CounterResult> ret;
|
||||
|
||||
if(m_pNVCounters->PrepareExperiment(counters, objectsCount))
|
||||
{
|
||||
FlushGPU(m_pDevice, m_pImmediateContext);
|
||||
|
||||
uint32_t passCount = m_pNVCounters->BeginExperiment();
|
||||
uint32_t sampleIndex = 0;
|
||||
vector<uint32_t> eventIDs;
|
||||
|
||||
for(uint32_t passIdx = 0; passIdx < passCount; ++passIdx)
|
||||
{
|
||||
m_pNVCounters->BeginPass(passIdx);
|
||||
|
||||
uint32_t eventStartID = 0;
|
||||
sampleIndex = 0;
|
||||
eventIDs.clear();
|
||||
|
||||
FillTimersNV(eventStartID, sampleIndex, eventIDs, m_pImmediateContext->GetRootDraw());
|
||||
|
||||
m_pNVCounters->EndPass(passIdx);
|
||||
}
|
||||
|
||||
m_pNVCounters->EndExperiment(eventIDs, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
#include "official/PerfKit/include/NvPmApi.h"
|
||||
#include "strings/string_utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
struct EnumCountersCtx
|
||||
{
|
||||
std::vector<GPUCounter> mExternalIds;
|
||||
std::vector<uint32_t> mInternalIds;
|
||||
std::vector<CounterDescription> mDescriptors;
|
||||
std::vector<CounterDescription> mExternalDescriptors;
|
||||
std::vector<uint32_t> mInternalDescriptors;
|
||||
|
||||
NvPmApi *mNvPmApi;
|
||||
|
||||
@@ -18,7 +21,12 @@ struct EnumCountersCtx
|
||||
|
||||
static bool NvPmResultFails(NVPMRESULT actual, char const *failMsg)
|
||||
{
|
||||
return actual != NVPM_OK;
|
||||
if(actual != NVPM_OK)
|
||||
{
|
||||
RDCWARN("NV GPU performance counters could not %s (code = %u)\n", failMsg, actual);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int NvPmCountCounters(NVPMCounterID unCounterID, const char *pcCounterName, void *pUserData)
|
||||
@@ -38,7 +46,7 @@ int NvPmGatherCounters(NVPMCounterID unCounterID, const char *pcCounterName, voi
|
||||
pEnumCtx->mExternalIds[i] = globalId;
|
||||
pEnumCtx->mInternalIds[i] = unCounterID;
|
||||
|
||||
CounterDescription &desc = pEnumCtx->mDescriptors[i];
|
||||
CounterDescription &desc = pEnumCtx->mExternalDescriptors[i];
|
||||
|
||||
NVPMUINT64 Attribute = 0;
|
||||
|
||||
@@ -61,35 +69,41 @@ int NvPmGatherCounters(NVPMCounterID unCounterID, const char *pcCounterName, voi
|
||||
};
|
||||
|
||||
pEnumCtx->mNvPmApi->GetCounterAttribute(unCounterID, NVPMA_COUNTER_DISPLAY, &Attribute);
|
||||
NVPMCOUNTERDISPLAY Display = static_cast<NVPMCOUNTERDISPLAY>(Attribute);
|
||||
|
||||
switch(Display)
|
||||
{
|
||||
case NVPM_CD_RATIO: desc.unit = CounterUnit::Ratio; break;
|
||||
|
||||
case NVPM_CD_RAW: desc.unit = CounterUnit::Cycles; break;
|
||||
}
|
||||
NVPMCOUNTERDISPLAY DisplayType = static_cast<NVPMCOUNTERDISPLAY>(Attribute);
|
||||
|
||||
pEnumCtx->mNvPmApi->GetCounterAttribute(unCounterID, NVPMA_COUNTER_DOMAIN, &Attribute);
|
||||
|
||||
pEnumCtx->mNvPmApi->GetCounterAttribute(unCounterID, NVPMA_COUNTER_VALUE_TYPE, &Attribute);
|
||||
NVPMCOUNTERVALUETYPE ValueType = static_cast<NVPMCOUNTERVALUETYPE>(Attribute);
|
||||
|
||||
switch(ValueType)
|
||||
{
|
||||
case NVPM_VALUE_TYPE_UINT64:
|
||||
{
|
||||
desc.resultType = CompType::UInt;
|
||||
desc.resultByteWidth = sizeof(uint64_t);
|
||||
}
|
||||
break;
|
||||
pEnumCtx->mInternalDescriptors[i] = (DisplayType << 1) | ValueType;
|
||||
|
||||
case NVPM_VALUE_TYPE_FLOAT64:
|
||||
if(ValueType == NVPM_VALUE_TYPE_UINT64)
|
||||
{
|
||||
if(DisplayType == NVPM_CD_RATIO)
|
||||
{
|
||||
desc.unit = CounterUnit::Ratio;
|
||||
desc.resultType = CompType::Double;
|
||||
desc.resultByteWidth = sizeof(double);
|
||||
}
|
||||
break;
|
||||
else
|
||||
{
|
||||
desc.unit = CounterUnit::Absolute;
|
||||
desc.resultType = CompType::UInt;
|
||||
desc.resultByteWidth = sizeof(uint64_t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DisplayType == NVPM_CD_RATIO)
|
||||
{
|
||||
RDCWARN(
|
||||
" normalization for counters with DisplayType == NVPM_CD_RATIO and ValueType == "
|
||||
"NVPM_VALUE_TYPE_FLOAT64 is unhandled");
|
||||
}
|
||||
desc.unit = CounterUnit::Ratio;
|
||||
desc.resultType = CompType::Double;
|
||||
desc.resultByteWidth = sizeof(double);
|
||||
}
|
||||
|
||||
char Description[512];
|
||||
@@ -110,19 +124,28 @@ int NvPmGatherCounters(NVPMCounterID unCounterID, const char *pcCounterName, voi
|
||||
return NVPM_OK;
|
||||
}
|
||||
|
||||
NVCounters::NVCounters() : mNvPmLib(NULL), mNvPmApi(NULL), mNvPmCtx(static_cast<uint64_t>(-1)) {}
|
||||
NVCounters::NVCounters()
|
||||
: mNvPmLib(NULL), mNvPmApi(NULL), mNvPmCtx(static_cast<uint64_t>(-1)), mObjectsCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
NVCounters::~NVCounters()
|
||||
{
|
||||
if(mObjectsCount != 0)
|
||||
{
|
||||
NvPmResultFails(mNvPmApi->DeleteObjects(mNvPmCtx), "call to 'NvPmApi::DeleteObjects'");
|
||||
mObjectsCount = 0;
|
||||
}
|
||||
|
||||
if(mNvPmCtx != static_cast<uint64_t>(-1))
|
||||
{
|
||||
mNvPmApi->DestroyContext(mNvPmCtx);
|
||||
NvPmResultFails(mNvPmApi->DestroyContext(mNvPmCtx), "call to 'NvPmApi::DestroyContext'");
|
||||
mNvPmCtx = static_cast<uint64_t>(-1);
|
||||
}
|
||||
|
||||
if(mNvPmApi != 0)
|
||||
{
|
||||
mNvPmApi->Shutdown();
|
||||
NvPmResultFails(mNvPmApi->Shutdown(), "call to 'NvPmApi::Shutdown'");
|
||||
mNvPmApi = NULL;
|
||||
}
|
||||
mNvPmLib = NULL;
|
||||
@@ -138,6 +161,7 @@ bool NVCounters::Init()
|
||||
mNvPmLib = Process::LoadModule("NvPmApi.Core.dll");
|
||||
if(mNvPmLib == NULL)
|
||||
{
|
||||
RDCWARN("NV GPU performance counters could not locate 'NvPmApi.Core.dll'");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -148,12 +172,12 @@ bool NVCounters::Init()
|
||||
return false;
|
||||
}
|
||||
|
||||
if(NvPmResultFails(pfnGetExportTable(&ETID_NvPmApi, (void **)&mNvPmApi), "Get 'NvPmApi' table"))
|
||||
if(NvPmResultFails(pfnGetExportTable(&ETID_NvPmApi, (void **)&mNvPmApi), "get 'NvPmApi' table"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(NvPmResultFails(mNvPmApi->Init(), "Init 'NvPmApi'"))
|
||||
if(NvPmResultFails(mNvPmApi->Init(), "init 'NvPmApi'"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -168,7 +192,7 @@ bool NVCounters::Init(ID3D11Device *pDevice)
|
||||
}
|
||||
|
||||
if(NvPmResultFails(mNvPmApi->CreateContextFromD3D11Device(pDevice, &mNvPmCtx),
|
||||
"Init 'NVPMContext' from ID3D11Device"))
|
||||
"init 'NVPMContext' from ID3D11Device"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -179,7 +203,8 @@ bool NVCounters::Init(ID3D11Device *pDevice)
|
||||
EnumCountersCtx ctx;
|
||||
ctx.mExternalIds.resize(NumCounters);
|
||||
ctx.mInternalIds.resize(NumCounters);
|
||||
ctx.mDescriptors.resize(NumCounters);
|
||||
ctx.mExternalDescriptors.resize(NumCounters);
|
||||
ctx.mInternalDescriptors.resize(NumCounters);
|
||||
ctx.mNvPmApi = mNvPmApi;
|
||||
ctx.mCurrentCounterId = 0;
|
||||
|
||||
@@ -187,7 +212,167 @@ bool NVCounters::Init(ID3D11Device *pDevice)
|
||||
|
||||
ctx.mExternalIds.swap(mExternalIds);
|
||||
ctx.mInternalIds.swap(mInternalIds);
|
||||
ctx.mDescriptors.swap(mDescriptors);
|
||||
ctx.mExternalDescriptors.swap(mExternalDescriptors);
|
||||
ctx.mInternalDescriptors.swap(mInternalDescriptors);
|
||||
|
||||
mSelectedExternalIds.reserve(NumCounters);
|
||||
mSelectedInternalIds.reserve(NumCounters);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NVCounters::PrepareExperiment(const std::vector<GPUCounter> &counters, uint32_t objectsCount)
|
||||
{
|
||||
if(NvPmResultFails(mNvPmApi->RemoveAllCounters(mNvPmCtx), "call to 'NvPmApi::RemoveAllCounters'"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mSelectedExternalIds.clear();
|
||||
mSelectedInternalIds.clear();
|
||||
|
||||
std::for_each(counters.begin(), counters.end(),
|
||||
[&selExternalIds = mSelectedExternalIds, &selInternalIds = mSelectedInternalIds,
|
||||
&internalIds = mInternalIds](GPUCounter counter) {
|
||||
const uint32_t externalId = static_cast<uint32_t>(counter) -
|
||||
static_cast<uint32_t>(GPUCounter::FirstNvidia);
|
||||
selExternalIds.push_back(counter);
|
||||
selInternalIds.push_back(internalIds[externalId]);
|
||||
});
|
||||
|
||||
if(NvPmResultFails(
|
||||
mNvPmApi->AddCounters(mNvPmCtx, static_cast<NVPMUINT>(mSelectedInternalIds.size()),
|
||||
mSelectedInternalIds.data()),
|
||||
"call to 'NvPmApi::AddCounters'"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mObjectsCount != objectsCount)
|
||||
{
|
||||
if(mObjectsCount != 0)
|
||||
{
|
||||
NvPmResultFails(mNvPmApi->DeleteObjects(mNvPmCtx), "call to 'NvPmApi::DeleteObjects'");
|
||||
mObjectsCount = 0;
|
||||
}
|
||||
|
||||
if(NvPmResultFails(mNvPmApi->ReserveObjects(mNvPmCtx, objectsCount),
|
||||
"call to 'NvPmApi::ReserveObjects'"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
mObjectsCount = objectsCount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t NVCounters::BeginExperiment() const
|
||||
{
|
||||
NVPMUINT NumPasses = 0;
|
||||
if(NvPmResultFails(mNvPmApi->BeginExperiment(mNvPmCtx, &NumPasses),
|
||||
"call to 'NvPmApi::BeginExperiment'"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return NumPasses;
|
||||
}
|
||||
|
||||
void NVCounters::EndExperiment(const std::vector<uint32_t> &eventIds,
|
||||
std::vector<CounterResult> &Result) const
|
||||
{
|
||||
NvPmResultFails(mNvPmApi->EndExperiment(mNvPmCtx), "call to 'NvPmApi::EndExperiment'");
|
||||
|
||||
// NVPMUINT NumCounters = mObjectsCount;
|
||||
// NVPMRESULT result = mNvPmApi->SampleEx(mNvPmCtx, Samples.data(), &NumCounters);
|
||||
// NvPmResultFails(result, "call to 'NvPmApi::SampleEx'");
|
||||
// mNvPmApi->GetCounterValue();
|
||||
|
||||
Result.reserve(mSelectedExternalIds.size() * mObjectsCount);
|
||||
|
||||
for(uint32_t counterIdx = 0; counterIdx < mSelectedExternalIds.size(); ++counterIdx)
|
||||
{
|
||||
const GPUCounter counter = mSelectedExternalIds[counterIdx];
|
||||
|
||||
const uint32_t externalId =
|
||||
static_cast<uint32_t>(counter) - static_cast<uint32_t>(GPUCounter::FirstNvidia);
|
||||
|
||||
const NVPMCounterID internalId = mInternalIds[externalId];
|
||||
|
||||
const uint32_t internalDesc = mInternalDescriptors[externalId];
|
||||
|
||||
const NVPMCOUNTERDISPLAY displayType = static_cast<NVPMCOUNTERDISPLAY>(internalDesc >> 1);
|
||||
const NVPMCOUNTERTYPE counterType = static_cast<NVPMCOUNTERTYPE>(internalDesc & 1);
|
||||
|
||||
if(counterType == NVPM_VALUE_TYPE_UINT64)
|
||||
{
|
||||
if(displayType == NVPM_CD_RATIO)
|
||||
{
|
||||
for(uint32_t i = 0; i < mObjectsCount; ++i)
|
||||
{
|
||||
NVPMUINT64 Value;
|
||||
NVPMUINT64 Cycles;
|
||||
NVPMUINT8 Overflow;
|
||||
NVPMRESULT result =
|
||||
mNvPmApi->GetCounterValueUint64(mNvPmCtx, internalId, i, &Value, &Cycles, &Overflow);
|
||||
|
||||
double Ratio = static_cast<double>(Value) / static_cast<double>(Cycles);
|
||||
Result.push_back(CounterResult(eventIds[i], counter, Ratio));
|
||||
|
||||
(void)result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t i = 0; i < mObjectsCount; ++i)
|
||||
{
|
||||
NVPMUINT64 Value;
|
||||
NVPMUINT64 Cycles;
|
||||
NVPMUINT8 Overflow;
|
||||
NVPMRESULT result =
|
||||
mNvPmApi->GetCounterValueUint64(mNvPmCtx, internalId, i, &Value, &Cycles, &Overflow);
|
||||
|
||||
Result.push_back(CounterResult(eventIds[i], counter, Value));
|
||||
|
||||
(void)result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t i = 0; i < mObjectsCount; ++i)
|
||||
{
|
||||
NVPMFLOAT64 Value;
|
||||
NVPMUINT64 Cycles;
|
||||
NVPMUINT8 Overflow;
|
||||
NVPMRESULT result =
|
||||
mNvPmApi->GetCounterValueFloat64(mNvPmCtx, internalId, i, &Value, &Cycles, &Overflow);
|
||||
|
||||
Result.push_back(CounterResult(eventIds[i], counter, Value));
|
||||
|
||||
(void)result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NVCounters::BeginPass(uint32_t passIdx) const
|
||||
{
|
||||
NvPmResultFails(mNvPmApi->BeginPass(mNvPmCtx, passIdx), "call to 'NvPmApi::BeginPass'");
|
||||
}
|
||||
|
||||
void NVCounters::EndPass(uint32_t passIdx) const
|
||||
{
|
||||
NvPmResultFails(mNvPmApi->EndPass(mNvPmCtx, passIdx), "call to 'NvPmApi::EndPass'");
|
||||
}
|
||||
|
||||
void NVCounters::BeginSample(uint32_t sampleIdx) const
|
||||
{
|
||||
RDCASSERT(sampleIdx < mObjectsCount);
|
||||
NvPmResultFails(mNvPmApi->BeginObject(mNvPmCtx, sampleIdx), "call to 'NvPmApi::BeginObject'");
|
||||
}
|
||||
|
||||
void NVCounters::EndSample(uint32_t sampleIdx) const
|
||||
{
|
||||
RDCASSERT(sampleIdx < mObjectsCount);
|
||||
NvPmResultFails(mNvPmApi->EndObject(mNvPmCtx, sampleIdx), "call to 'NvPmApi::EndObject'");
|
||||
}
|
||||
|
||||
@@ -20,17 +20,33 @@ public:
|
||||
{
|
||||
const uint32_t LocalId =
|
||||
static_cast<uint32_t>(counterID) - static_cast<uint32_t>(GPUCounter::FirstNvidia);
|
||||
return mDescriptors[LocalId];
|
||||
return mExternalDescriptors[LocalId];
|
||||
}
|
||||
|
||||
bool PrepareExperiment(const std::vector<GPUCounter> &counters, uint32_t objectsCount);
|
||||
|
||||
// returns num passes
|
||||
uint32_t BeginExperiment() const;
|
||||
void EndExperiment(const std::vector<uint32_t> &eventIds, std::vector<CounterResult> &Result) const;
|
||||
|
||||
void BeginPass(uint32_t passIdx) const;
|
||||
void EndPass(uint32_t passIdx) const;
|
||||
|
||||
void BeginSample(uint32_t sampleIdx) const;
|
||||
void EndSample(uint32_t sampleIdx) const;
|
||||
|
||||
private:
|
||||
bool Init(void);
|
||||
|
||||
void *mNvPmLib;
|
||||
struct _NvPmApi *mNvPmApi;
|
||||
uint64_t mNvPmCtx;
|
||||
uint32_t mObjectsCount;
|
||||
|
||||
std::vector<GPUCounter> mExternalIds;
|
||||
std::vector<uint32_t> mInternalIds;
|
||||
std::vector<CounterDescription> mDescriptors;
|
||||
std::vector<GPUCounter> mSelectedExternalIds;
|
||||
std::vector<uint32_t> mSelectedInternalIds;
|
||||
std::vector<CounterDescription> mExternalDescriptors;
|
||||
std::vector<uint32_t> mInternalDescriptors;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user