mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-10 08:41:04 +00:00
AMD GPUPerfAPI 3.0 Preview Integration.
Direct3D11, Direct3D12, OpenGL, and Vulkan supported. Fixes Direct3D11 counter command isolation.
This commit is contained in:
@@ -22,10 +22,15 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include "vk_core.h"
|
||||
#include "vk_replay.h"
|
||||
#include "vk_resources.h"
|
||||
|
||||
#include "driver/ihv/amd/amd_counters.h"
|
||||
#include "driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-VK.h"
|
||||
|
||||
vector<GPUCounter> VulkanReplay::EnumerateCounters()
|
||||
{
|
||||
vector<GPUCounter> ret;
|
||||
@@ -55,6 +60,12 @@ vector<GPUCounter> VulkanReplay::EnumerateCounters()
|
||||
ret.push_back(GPUCounter::CSInvocations);
|
||||
}
|
||||
|
||||
if(m_pAMDCounters)
|
||||
{
|
||||
vector<GPUCounter> amdCounters = m_pAMDCounters->GetPublicCounterIds();
|
||||
ret.insert(ret.end(), amdCounters.begin(), amdCounters.end());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -62,6 +73,18 @@ CounterDescription VulkanReplay::DescribeCounter(GPUCounter counterID)
|
||||
{
|
||||
CounterDescription desc = {};
|
||||
desc.counter = counterID;
|
||||
|
||||
/////AMD//////
|
||||
if(IsAMDCounter(counterID))
|
||||
{
|
||||
if(m_pAMDCounters)
|
||||
{
|
||||
desc = m_pAMDCounters->GetCounterDescription(counterID);
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
// 6839CB5B-FBD2-4550-B606-8C65157C684C
|
||||
desc.uuid.words[0] = 0x6839CB5B;
|
||||
desc.uuid.words[1] = 0xFBD24550;
|
||||
@@ -176,6 +199,172 @@ CounterDescription VulkanReplay::DescribeCounter(GPUCounter counterID)
|
||||
return desc;
|
||||
}
|
||||
|
||||
struct VulkanAMDDrawCallback : public VulkanDrawcallCallback
|
||||
{
|
||||
VulkanAMDDrawCallback(WrappedVulkan *dev, VulkanReplay *rp, uint32_t &sampleIndex,
|
||||
vector<uint32_t> &eventIDs)
|
||||
: m_pDriver(dev), m_pReplay(rp), m_pSampleId(&sampleIndex), m_pEventIds(&eventIDs)
|
||||
{
|
||||
m_pDriver->SetDrawcallCB(this);
|
||||
}
|
||||
|
||||
virtual ~VulkanAMDDrawCallback() { m_pDriver->SetDrawcallCB(NULL); }
|
||||
void PreDraw(uint32_t eid, VkCommandBuffer cmd) override
|
||||
{
|
||||
m_pEventIds->push_back(eid);
|
||||
|
||||
VkCommandBuffer realCmdBuffer = Unwrap(cmd);
|
||||
|
||||
if(m_begunCommandBuffers.find(realCmdBuffer) == m_begunCommandBuffers.end())
|
||||
{
|
||||
m_begunCommandBuffers.insert(realCmdBuffer);
|
||||
|
||||
m_pReplay->GetAMDCounters()->BeginSampleList(realCmdBuffer);
|
||||
}
|
||||
|
||||
m_pReplay->GetAMDCounters()->BeginSampleInSampleList(*m_pSampleId, realCmdBuffer);
|
||||
|
||||
++*m_pSampleId;
|
||||
}
|
||||
|
||||
bool PostDraw(uint32_t eid, VkCommandBuffer cmd) override
|
||||
{
|
||||
VkCommandBuffer realCmdBuffer = Unwrap(cmd);
|
||||
|
||||
m_pReplay->GetAMDCounters()->EndSampleInSampleList(realCmdBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
void PreEndCommandBuffer(VkCommandBuffer cmd) override
|
||||
{
|
||||
VkCommandBuffer realCmdBuffer = Unwrap(cmd);
|
||||
|
||||
auto iter = m_begunCommandBuffers.find(realCmdBuffer);
|
||||
|
||||
if(iter != m_begunCommandBuffers.end())
|
||||
{
|
||||
m_pReplay->GetAMDCounters()->EndSampleList(*iter);
|
||||
m_begunCommandBuffers.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void PostRedraw(uint32_t eid, VkCommandBuffer cmd) override {}
|
||||
// we don't need to distinguish, call the Draw functions
|
||||
void PreDispatch(uint32_t eid, VkCommandBuffer cmd) override { PreDraw(eid, cmd); }
|
||||
bool PostDispatch(uint32_t eid, VkCommandBuffer cmd) override { return PostDraw(eid, cmd); }
|
||||
void PostRedispatch(uint32_t eid, VkCommandBuffer cmd) override { PostRedraw(eid, cmd); }
|
||||
void PreMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) override { PreDraw(eid, cmd); }
|
||||
bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) override
|
||||
{
|
||||
return PostDraw(eid, cmd);
|
||||
}
|
||||
void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) override
|
||||
{
|
||||
PostRedraw(eid, cmd);
|
||||
}
|
||||
|
||||
void AliasEvent(uint32_t primary, uint32_t alias) override
|
||||
{
|
||||
m_AliasEvents.push_back(std::make_pair(primary, alias));
|
||||
}
|
||||
|
||||
uint32_t *m_pSampleId;
|
||||
WrappedVulkan *m_pDriver;
|
||||
VulkanReplay *m_pReplay;
|
||||
vector<uint32_t> *m_pEventIds;
|
||||
set<VkCommandBuffer> m_begunCommandBuffers;
|
||||
// events which are the 'same' from being the same command buffer resubmitted
|
||||
// multiple times in the frame. We will only get the full callback when we're
|
||||
// recording the command buffer, and will be given the first EID. After that
|
||||
// we'll just be told which other EIDs alias this event.
|
||||
vector<pair<uint32_t, uint32_t> > m_AliasEvents;
|
||||
};
|
||||
|
||||
void VulkanReplay::FillTimersAMD(uint32_t *eventStartID, uint32_t *sampleIndex,
|
||||
vector<uint32_t> *eventIDs)
|
||||
{
|
||||
uint32_t maxEID = m_pDriver->GetMaxEID();
|
||||
|
||||
m_pAMDDrawCallback = new VulkanAMDDrawCallback(m_pDriver, this, *sampleIndex, *eventIDs);
|
||||
|
||||
// replay the events to perform all the queries
|
||||
m_pDriver->ReplayLog(*eventStartID, maxEID, eReplay_Full);
|
||||
}
|
||||
|
||||
vector<CounterResult> VulkanReplay::FetchCountersAMD(const vector<GPUCounter> &counters)
|
||||
{
|
||||
m_pAMDCounters->DisableAllCounters();
|
||||
|
||||
// enable counters it needs
|
||||
for(size_t i = 0; i < counters.size(); i++)
|
||||
{
|
||||
// This function is only called internally, and violating this assertion means our
|
||||
// caller has invoked this method incorrectly
|
||||
RDCASSERT(IsAMDCounter(counters[i]));
|
||||
m_pAMDCounters->EnableCounter(counters[i]);
|
||||
}
|
||||
|
||||
uint32_t sessionID = m_pAMDCounters->BeginSession();
|
||||
|
||||
uint32_t passCount = m_pAMDCounters->GetPassCount();
|
||||
|
||||
uint32_t sampleIndex = 0;
|
||||
|
||||
vector<uint32_t> eventIDs;
|
||||
|
||||
for(uint32_t i = 0; i < passCount; i++)
|
||||
{
|
||||
m_pAMDCounters->BeginPass();
|
||||
|
||||
uint32_t eventStartID = 0;
|
||||
|
||||
sampleIndex = 0;
|
||||
|
||||
eventIDs.clear();
|
||||
|
||||
FillTimersAMD(&eventStartID, &sampleIndex, &eventIDs);
|
||||
|
||||
m_pAMDCounters->EndPass();
|
||||
}
|
||||
|
||||
m_pAMDCounters->EndSesssion();
|
||||
|
||||
std::vector<CounterResult> ret =
|
||||
m_pAMDCounters->GetCounterData(sessionID, sampleIndex, eventIDs, counters);
|
||||
|
||||
for(size_t i = 0; i < m_pAMDDrawCallback->m_AliasEvents.size(); i++)
|
||||
{
|
||||
for(size_t c = 0; c < counters.size(); c++)
|
||||
{
|
||||
CounterResult search;
|
||||
search.counter = counters[c];
|
||||
search.eventId = m_pAMDDrawCallback->m_AliasEvents[i].first;
|
||||
|
||||
// find the result we're aliasing
|
||||
auto it = std::find(ret.begin(), ret.end(), search);
|
||||
if(it != ret.end())
|
||||
{
|
||||
// duplicate the result and append
|
||||
CounterResult aliased = *it;
|
||||
aliased.eventId = m_pAMDDrawCallback->m_AliasEvents[i].second;
|
||||
ret.push_back(aliased);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Expected to find alias-target result for EID %u counter %u, but didn't",
|
||||
search.eventId, search.counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE(m_pAMDDrawCallback);
|
||||
|
||||
// sort so that the alias results appear in the right places
|
||||
std::sort(ret.begin(), ret.end());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct VulkanGPUTimerCallback : public VulkanDrawcallCallback
|
||||
{
|
||||
VulkanGPUTimerCallback(WrappedVulkan *vk, VulkanReplay *rp, VkQueryPool tsqp, VkQueryPool occqp,
|
||||
@@ -189,7 +378,7 @@ struct VulkanGPUTimerCallback : public VulkanDrawcallCallback
|
||||
m_pDriver->SetDrawcallCB(this);
|
||||
}
|
||||
~VulkanGPUTimerCallback() { m_pDriver->SetDrawcallCB(NULL); }
|
||||
void PreDraw(uint32_t eid, VkCommandBuffer cmd)
|
||||
void PreDraw(uint32_t eid, VkCommandBuffer cmd) override
|
||||
{
|
||||
if(m_OcclusionQueryPool != VK_NULL_HANDLE)
|
||||
ObjDisp(cmd)->CmdBeginQuery(Unwrap(cmd), m_OcclusionQueryPool, (uint32_t)m_Results.size(),
|
||||
@@ -200,7 +389,7 @@ struct VulkanGPUTimerCallback : public VulkanDrawcallCallback
|
||||
m_TimeStampQueryPool, (uint32_t)(m_Results.size() * 2 + 0));
|
||||
}
|
||||
|
||||
bool PostDraw(uint32_t eid, VkCommandBuffer cmd)
|
||||
bool PostDraw(uint32_t eid, VkCommandBuffer cmd) override
|
||||
{
|
||||
ObjDisp(cmd)->CmdWriteTimestamp(Unwrap(cmd), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
m_TimeStampQueryPool, (uint32_t)(m_Results.size() * 2 + 1));
|
||||
@@ -212,19 +401,26 @@ struct VulkanGPUTimerCallback : public VulkanDrawcallCallback
|
||||
return false;
|
||||
}
|
||||
|
||||
void PostRedraw(uint32_t eid, VkCommandBuffer cmd) {}
|
||||
void PostRedraw(uint32_t eid, VkCommandBuffer cmd) override {}
|
||||
// we don't need to distinguish, call the Draw functions
|
||||
void PreDispatch(uint32_t eid, VkCommandBuffer cmd) { PreDraw(eid, cmd); }
|
||||
bool PostDispatch(uint32_t eid, VkCommandBuffer cmd) { return PostDraw(eid, cmd); }
|
||||
void PostRedispatch(uint32_t eid, VkCommandBuffer cmd) { PostRedraw(eid, cmd); }
|
||||
void PreMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { PreDraw(eid, cmd); }
|
||||
bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { return PostDraw(eid, cmd); }
|
||||
void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { PostRedraw(eid, cmd); }
|
||||
void AliasEvent(uint32_t primary, uint32_t alias)
|
||||
void PreDispatch(uint32_t eid, VkCommandBuffer cmd) override { PreDraw(eid, cmd); }
|
||||
bool PostDispatch(uint32_t eid, VkCommandBuffer cmd) override { return PostDraw(eid, cmd); }
|
||||
void PostRedispatch(uint32_t eid, VkCommandBuffer cmd) override { PostRedraw(eid, cmd); }
|
||||
void PreMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) override { PreDraw(eid, cmd); }
|
||||
bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) override
|
||||
{
|
||||
return PostDraw(eid, cmd);
|
||||
}
|
||||
void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) override
|
||||
{
|
||||
PostRedraw(eid, cmd);
|
||||
}
|
||||
void AliasEvent(uint32_t primary, uint32_t alias) override
|
||||
{
|
||||
m_AliasEvents.push_back(std::make_pair(primary, alias));
|
||||
}
|
||||
|
||||
void PreEndCommandBuffer(VkCommandBuffer cmd) override {}
|
||||
WrappedVulkan *m_pDriver;
|
||||
VulkanReplay *m_pReplay;
|
||||
VkQueryPool m_TimeStampQueryPool;
|
||||
@@ -242,6 +438,30 @@ vector<CounterResult> VulkanReplay::FetchCounters(const vector<GPUCounter> &coun
|
||||
{
|
||||
uint32_t maxEID = m_pDriver->GetMaxEID();
|
||||
|
||||
vector<GPUCounter> vkCounters;
|
||||
std::copy_if(counters.begin(), counters.end(), std::back_inserter(vkCounters),
|
||||
[](const GPUCounter &c) { return !IsAMDCounter(c); });
|
||||
|
||||
vector<CounterResult> ret;
|
||||
|
||||
if(m_pAMDCounters)
|
||||
{
|
||||
// Filter out the AMD counters
|
||||
vector<GPUCounter> amdCounters;
|
||||
std::copy_if(counters.begin(), counters.end(), std::back_inserter(amdCounters),
|
||||
[](const GPUCounter &c) { return IsAMDCounter(c); });
|
||||
|
||||
if(!amdCounters.empty())
|
||||
{
|
||||
ret = FetchCountersAMD(amdCounters);
|
||||
}
|
||||
}
|
||||
|
||||
if(vkCounters.empty())
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
VkPhysicalDeviceFeatures availableFeatures = m_pDriver->GetDeviceFeatures();
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
@@ -277,9 +497,9 @@ vector<CounterResult> VulkanReplay::FetchCounters(const vector<GPUCounter> &coun
|
||||
bool occlNeeded = false;
|
||||
bool statsNeeded = false;
|
||||
|
||||
for(size_t c = 0; c < counters.size(); c++)
|
||||
for(size_t c = 0; c < vkCounters.size(); c++)
|
||||
{
|
||||
switch(counters[c])
|
||||
switch(vkCounters[c])
|
||||
{
|
||||
case GPUCounter::InputVerticesRead:
|
||||
case GPUCounter::IAPrimitives:
|
||||
@@ -374,18 +594,16 @@ vector<CounterResult> VulkanReplay::FetchCounters(const vector<GPUCounter> &coun
|
||||
ObjDisp(dev)->DestroyQueryPool(Unwrap(dev), pipeStatsPool, NULL);
|
||||
}
|
||||
|
||||
vector<CounterResult> ret;
|
||||
|
||||
for(size_t i = 0; i < cb.m_Results.size(); i++)
|
||||
{
|
||||
for(size_t c = 0; c < counters.size(); c++)
|
||||
for(size_t c = 0; c < vkCounters.size(); c++)
|
||||
{
|
||||
CounterResult result;
|
||||
|
||||
result.eventId = cb.m_Results[i];
|
||||
result.counter = counters[c];
|
||||
result.counter = vkCounters[c];
|
||||
|
||||
switch(counters[c])
|
||||
switch(vkCounters[c])
|
||||
{
|
||||
case GPUCounter::EventGPUDuration:
|
||||
{
|
||||
@@ -419,10 +637,10 @@ vector<CounterResult> VulkanReplay::FetchCounters(const vector<GPUCounter> &coun
|
||||
|
||||
for(size_t i = 0; i < cb.m_AliasEvents.size(); i++)
|
||||
{
|
||||
for(size_t c = 0; c < counters.size(); c++)
|
||||
for(size_t c = 0; c < vkCounters.size(); c++)
|
||||
{
|
||||
CounterResult search;
|
||||
search.counter = counters[c];
|
||||
search.counter = vkCounters[c];
|
||||
search.eventId = cb.m_AliasEvents[i].first;
|
||||
|
||||
// find the result we're aliasing
|
||||
|
||||
Reference in New Issue
Block a user