Implemented data retrieval from selected NV counters

This commit is contained in:
reinsteam
2018-03-21 17:53:08 +09:00
committed by Baldur Karlsson
parent f3cb0e1854
commit 7347a11dff
3 changed files with 323 additions and 31 deletions
+91
View File
@@ -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;
}
+214 -29
View File
@@ -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'");
}
+18 -2
View File
@@ -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;
};