Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Adds support for PE performance metrics in the D3D9 backend
  • Loading branch information
Tinob committed Apr 3, 2013
1 parent d06379f commit c4bc20b
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj
Expand Up @@ -199,6 +199,7 @@
<ClCompile Include="Src\FramebufferManager.cpp" />
<ClCompile Include="Src\main.cpp" />
<ClCompile Include="Src\NativeVertexFormat.cpp" />
<ClCompile Include="Src\PerfQuery.cpp" />
<ClCompile Include="Src\PixelShaderCache.cpp" />
<ClCompile Include="Src\Render.cpp" />
<ClCompile Include="Src\stdafx.cpp">
Expand All @@ -222,6 +223,7 @@
<ClInclude Include="Src\FramebufferManager.h" />
<ClInclude Include="Src\Globals.h" />
<ClInclude Include="Src\main.h" />
<ClInclude Include="Src\PerfQuery.h" />
<ClInclude Include="Src\PixelShaderCache.h" />
<ClInclude Include="Src\Render.h" />
<ClInclude Include="Src\stdafx.h" />
Expand Down
Expand Up @@ -39,6 +39,9 @@
<ClCompile Include="Src\TextureConverter.cpp">
<Filter>D3D</Filter>
</ClCompile>
<ClCompile Include="Src\PerfQuery.cpp">
<Filter>Render</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Globals.h" />
Expand Down Expand Up @@ -78,6 +81,9 @@
<ClInclude Include="Src\TextureConverter.h">
<Filter>D3D</Filter>
</ClInclude>
<ClInclude Include="Src\PerfQuery.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D">
Expand Down
146 changes: 146 additions & 0 deletions Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.cpp
@@ -0,0 +1,146 @@
#include "RenderBase.h"

#include "D3DBase.h"
#include "PerfQuery.h"

namespace DX9 {

PerfQuery::PerfQuery()
: m_query_read_pos()
, m_query_count()
{
for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
{
D3D::dev->CreateQuery(D3DQUERYTYPE_OCCLUSION, &m_query_buffer[i].query);
}
ResetQuery();
}

PerfQuery::~PerfQuery()
{
for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
{
m_query_buffer[i].query->Release();
}
}

void PerfQuery::EnableQuery(PerfQueryGroup type)
{
// Is this sane?
if (m_query_count > ARRAYSIZE(m_query_buffer) / 2)
WeakFlush();

if (ARRAYSIZE(m_query_buffer) == m_query_count)
{
// TODO
FlushOne();
ERROR_LOG(VIDEO, "Flushed query buffer early!");
}

// start query
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
{
auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)];
entry.query->Issue(D3DISSUE_BEGIN);
entry.query_type = type;
++m_query_count;
}
}

void PerfQuery::DisableQuery(PerfQueryGroup type)
{
// stop query
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
{
auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ARRAYSIZE(m_query_buffer)-1) % ARRAYSIZE(m_query_buffer)];
entry.query->Issue(D3DISSUE_END);
}
}

void PerfQuery::ResetQuery()
{
m_query_count = 0;
std::fill_n(m_results, ARRAYSIZE(m_results), 0);
}

u32 PerfQuery::GetQueryResult(PerfQueryType type)
{
u32 result = 0;

if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
{
result = m_results[PQG_ZCOMP_ZCOMPLOC];
}
else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
{
result = m_results[PQG_ZCOMP];
}
else if (type == PQ_BLEND_INPUT)
{
result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
}
else if (type == PQ_EFB_COPY_CLOCKS)
{
result = m_results[PQG_EFB_COPY_CLOCKS];
}

return result / 4;
}

void PerfQuery::FlushOne()
{
auto& entry = m_query_buffer[m_query_read_pos];

UINT64 result = 0;
HRESULT hr = S_FALSE;
while (hr != S_OK && hr != D3DERR_DEVICELOST)
{
// TODO: Might cause us to be stuck in an infinite loop!
hr = entry.query->GetData(&result, sizeof(result), D3DGETDATA_FLUSH);
}

// NOTE: Reported pixel metrics should be referenced to native resolution
m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();

m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
--m_query_count;
}

// TODO: could selectively flush things, but I don't think that will do much
void PerfQuery::FlushResults()
{
while (!IsFlushed())
FlushOne();
}

void PerfQuery::WeakFlush()
{
while (!IsFlushed())
{
auto& entry = m_query_buffer[m_query_read_pos];

UINT64 result = 0;
HRESULT hr = entry.query->GetData(&result, sizeof(result), 0);

if (hr == S_OK)
{
// NOTE: Reported pixel metrics should be referenced to native resolution
m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();

m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer);
--m_query_count;
}
else
{
break;
}
}
}

bool PerfQuery::IsFlushed() const
{
return 0 == m_query_count;
}


} // namespace
46 changes: 46 additions & 0 deletions Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.h
@@ -0,0 +1,46 @@
#ifndef _PERFQUERY_H_
#define _PERFQUERY_H_

#include "PerfQueryBase.h"

namespace DX9 {

class PerfQuery : public PerfQueryBase
{
public:
PerfQuery();
~PerfQuery();

void EnableQuery(PerfQueryGroup type);
void DisableQuery(PerfQueryGroup type);
void ResetQuery();
u32 GetQueryResult(PerfQueryType type);
void FlushResults();
bool IsFlushed() const;

private:
struct ActiveQuery
{
IDirect3DQuery9* query;
PerfQueryGroup query_type;
};

void WeakFlush();

// Only use when non-empty
void FlushOne();

// when testing in SMS: 64 was too small, 128 was ok
static const int PERF_QUERY_BUFFER_SIZE = 512;

ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
int m_query_read_pos;

// TODO: sloppy
volatile int m_query_count;
volatile u32 m_results[PQG_NUM_MEMBERS];
};

} // namespace

#endif // _PERFQUERY_H_
4 changes: 3 additions & 1 deletion Source/Plugins/Plugin_VideoDX9/Src/Render.cpp
Expand Up @@ -55,7 +55,7 @@
#include "BPFunctions.h"
#include "FPSCounter.h"
#include "ConfigManager.h"

#include "PerfQuery.h"
#include <strsafe.h>


Expand Down Expand Up @@ -88,6 +88,7 @@ void SetupDeviceObjects()
VertexShaderCache::Init();
PixelShaderCache::Init();
g_vertex_manager->CreateDeviceObjects();
g_perf_query = new PerfQuery;
// Texture cache will recreate themselves over time.
}

Expand All @@ -100,6 +101,7 @@ void TeardownDeviceObjects()
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
delete g_framebuffer_manager;
delete g_perf_query;
D3D::font.Shutdown();
TextureCache::Invalidate();
VertexLoaderManager::Shutdown();
Expand Down
5 changes: 3 additions & 2 deletions Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
Expand Up @@ -378,7 +378,8 @@ void VertexManager::vFlush()

}
PrepareDrawBuffers(stride);
g_nativeVertexFmt->SetupVertexPointers();
g_nativeVertexFmt->SetupVertexPointers();
g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
if(m_buffers_count)
{
DrawVertexBuffer(stride);
Expand All @@ -387,7 +388,7 @@ void VertexManager::vFlush()
{
DrawVertexArray(stride);
}

g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
if (useDstAlpha && !useDualSource)
{
if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components))
Expand Down

0 comments on commit c4bc20b

Please sign in to comment.