mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-30 01:29:42 -06:00
Merge branch 'master' into vertex-loader-cleanup
Conflicts: Source/Core/Common/Src/CommonFuncs.h Source/Core/VideoCommon/Src/VertexLoader.cpp
This commit is contained in:
@ -51,7 +51,9 @@ void VideoBackend::UpdateFPSDisplay(const char *text)
|
||||
}
|
||||
void InitInterface()
|
||||
{
|
||||
#if defined(USE_EGL) && USE_EGL
|
||||
#ifdef ANDROID
|
||||
GLInterface = new cInterfaceBase;
|
||||
#elif defined(USE_EGL) && USE_EGL
|
||||
GLInterface = new cInterfaceEGL;
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
GLInterface = new cInterfaceWX;
|
||||
|
@ -69,7 +69,7 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
|
||||
#define GL_REPORT_PROGRAM_ERROR() (void)0
|
||||
#endif
|
||||
|
||||
#if defined __APPLE__ || defined __linux__ || defined _WIN32
|
||||
#if (defined __APPLE__ || defined __linux__ || defined _WIN32) && !(defined _M_ARM)
|
||||
#include <Cg/cg.h>
|
||||
#include <Cg/cgGL.h>
|
||||
#define HAVE_CG 1
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "GLUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "x64ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
|
133
Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp
Normal file
133
Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "RenderBase.h"
|
||||
#include "GLUtil.h"
|
||||
#include "PerfQuery.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
PerfQuery::PerfQuery()
|
||||
: m_query_read_pos()
|
||||
, m_query_count()
|
||||
{
|
||||
for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
|
||||
glGenQueries(1, &m_query_buffer[i].query_id);
|
||||
|
||||
ResetQuery();
|
||||
}
|
||||
|
||||
PerfQuery::~PerfQuery()
|
||||
{
|
||||
for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i)
|
||||
glDeleteQueries(1, &m_query_buffer[i].query_id);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)];
|
||||
|
||||
glBeginQuery(GL_SAMPLES_PASSED, entry.query_id);
|
||||
entry.query_type = type;
|
||||
|
||||
++m_query_count;
|
||||
}
|
||||
}
|
||||
|
||||
void PerfQuery::DisableQuery(PerfQueryGroup type)
|
||||
{
|
||||
// stop query
|
||||
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
|
||||
{
|
||||
glEndQuery(GL_SAMPLES_PASSED);
|
||||
}
|
||||
}
|
||||
|
||||
bool PerfQuery::IsFlushed() const
|
||||
{
|
||||
return 0 == m_query_count;
|
||||
}
|
||||
|
||||
void PerfQuery::FlushOne()
|
||||
{
|
||||
auto& entry = m_query_buffer[m_query_read_pos];
|
||||
|
||||
GLuint result = 0;
|
||||
glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result);
|
||||
|
||||
// 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];
|
||||
|
||||
GLuint result = GL_FALSE;
|
||||
glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE, &result);
|
||||
|
||||
if (GL_TRUE == result)
|
||||
{
|
||||
FlushOne();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace
|
46
Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h
Normal file
46
Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef _PERFQUERY_H_
|
||||
#define _PERFQUERY_H_
|
||||
|
||||
#include "PerfQueryBase.h"
|
||||
|
||||
namespace OGL {
|
||||
|
||||
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
|
||||
{
|
||||
GLuint query_id;
|
||||
PerfQueryGroup query_type;
|
||||
};
|
||||
|
||||
// when testing in SMS: 64 was too small, 128 was ok
|
||||
static const u32 PERF_QUERY_BUFFER_SIZE = 512;
|
||||
|
||||
void WeakFlush();
|
||||
// Only use when non-empty
|
||||
void FlushOne();
|
||||
|
||||
// This contains gl query objects with unretrieved results.
|
||||
ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
|
||||
u32 m_query_read_pos;
|
||||
|
||||
// TODO: sloppy
|
||||
volatile u32 m_query_count;
|
||||
volatile u32 m_results[PQG_NUM_MEMBERS];
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _PERFQUERY_H_
|
@ -264,7 +264,8 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
|
||||
static int num_failures = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file(szTemp);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, szTemp, std::ios_base::out);
|
||||
file << pstrprogram;
|
||||
file.close();
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "GLUtil.h"
|
||||
#include "WxUtils.h"
|
||||
|
||||
#include "FileUtil.h"
|
||||
|
||||
@ -956,20 +957,23 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
s_blendMode = newval;
|
||||
}
|
||||
|
||||
void DumpFrame(const std::vector<u8>& data, int w, int h)
|
||||
{
|
||||
#if defined(HAVE_LIBAV) || defined(_WIN32)
|
||||
if (g_ActiveConfig.bDumpFrames && !data.empty())
|
||||
{
|
||||
AVIDump::AddFrame(&data[0], w, h);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// This function has the final picture. We adjust the aspect ratio here.
|
||||
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
|
||||
{
|
||||
static int w = 0, h = 0;
|
||||
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
|
||||
{
|
||||
if (g_ActiveConfig.bDumpFrames && frame_data)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
AVIDump::AddFrame(frame_data);
|
||||
#elif defined HAVE_LIBAV
|
||||
AVIDump::AddFrame((u8*)frame_data, w, h);
|
||||
#endif
|
||||
}
|
||||
DumpFrame(frame_data, w, h);
|
||||
Core::Callback_VideoCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
@ -979,14 +983,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0))
|
||||
{
|
||||
if (g_ActiveConfig.bDumpFrames && frame_data)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
AVIDump::AddFrame(frame_data);
|
||||
#elif defined HAVE_LIBAV
|
||||
AVIDump::AddFrame((u8*)frame_data, w, h);
|
||||
#endif
|
||||
}
|
||||
DumpFrame(frame_data, w, h);
|
||||
Core::Callback_VideoCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
@ -1149,16 +1146,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
if (g_ActiveConfig.bDumpFrames)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
|
||||
if (!frame_data || w != flipped_trc.GetWidth() ||
|
||||
if (frame_data.empty() || w != flipped_trc.GetWidth() ||
|
||||
h != flipped_trc.GetHeight())
|
||||
{
|
||||
if (frame_data) delete[] frame_data;
|
||||
w = flipped_trc.GetWidth();
|
||||
h = flipped_trc.GetHeight();
|
||||
frame_data = new char[3 * w * h];
|
||||
frame_data.resize(3 * w * h);
|
||||
}
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
|
||||
glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
|
||||
if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
|
||||
{
|
||||
if (!bLastFrameDumped)
|
||||
@ -1179,12 +1175,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
}
|
||||
if (bAVIDumping)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
AVIDump::AddFrame(frame_data);
|
||||
#else
|
||||
FlipImageData((u8*)frame_data, w, h);
|
||||
AVIDump::AddFrame((u8*)frame_data, w, h);
|
||||
#ifndef _WIN32
|
||||
FlipImageData(&frame_data[0], w, h);
|
||||
#endif
|
||||
|
||||
AVIDump::AddFrame(&frame_data[0], w, h);
|
||||
}
|
||||
|
||||
bLastFrameDumped = true;
|
||||
@ -1196,12 +1191,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
{
|
||||
if (bLastFrameDumped && bAVIDumping)
|
||||
{
|
||||
if (frame_data)
|
||||
{
|
||||
delete[] frame_data;
|
||||
frame_data = NULL;
|
||||
w = h = 0;
|
||||
}
|
||||
std::vector<u8>().swap(frame_data);
|
||||
w = h = 0;
|
||||
AVIDump::Stop();
|
||||
bAVIDumping = false;
|
||||
OSD::AddMessage("Stop dumping frames", 2000);
|
||||
@ -1215,9 +1206,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
std::string movie_file_name;
|
||||
w = GetTargetRectangle().GetWidth();
|
||||
h = GetTargetRectangle().GetHeight();
|
||||
frame_data = new char[3 * w * h];
|
||||
frame_data.resize(3 * w * h);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
|
||||
glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
|
||||
if (GL_REPORT_ERROR() == GL_NO_ERROR)
|
||||
{
|
||||
if (!bLastFrameDumped)
|
||||
@ -1228,21 +1219,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
OSD::AddMessage("Error opening framedump.raw for writing.", 2000);
|
||||
else
|
||||
{
|
||||
char msg [255];
|
||||
sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h);
|
||||
OSD::AddMessage(msg, 2000);
|
||||
OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h).c_str(), 2000);
|
||||
}
|
||||
}
|
||||
if (pFrameDump)
|
||||
{
|
||||
FlipImageData((u8*)frame_data, w, h);
|
||||
pFrameDump.WriteBytes(frame_data, w * 3 * h);
|
||||
FlipImageData(&frame_data[0], w, h);
|
||||
pFrameDump.WriteBytes(&frame_data[0], w * 3 * h);
|
||||
pFrameDump.Flush();
|
||||
}
|
||||
bLastFrameDumped = true;
|
||||
}
|
||||
|
||||
delete[] frame_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1433,6 +1420,7 @@ void Renderer::SetDepthMode()
|
||||
else
|
||||
{
|
||||
// if the test is disabled write is disabled too
|
||||
// TODO: When PE performance metrics are being emulated via occlusion queries, we should (probably?) enable depth test with depth function ALWAYS here
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
@ -1552,7 +1540,7 @@ void TakeScreenshot(ScrStrct* threadStruct)
|
||||
|
||||
// Save the screenshot and finally kill the wxImage object
|
||||
// This is really expensive when saving to PNG, but not at all when using BMP
|
||||
threadStruct->img->SaveFile(wxString::FromAscii(threadStruct->filename.c_str()),
|
||||
threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename),
|
||||
wxBITMAP_TYPE_PNG);
|
||||
threadStruct->img->Destroy();
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Debugger.h"
|
||||
#include "PerfQueryBase.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
@ -213,7 +214,10 @@ void VertexManager::vFlush()
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here.
|
||||
if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid);
|
||||
|
||||
g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||
Draw();
|
||||
g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||
//ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT));
|
||||
|
||||
// run through vertex groups again to set alpha
|
||||
if (useDstAlpha && !dualSourcePossible)
|
||||
@ -243,10 +247,12 @@ void VertexManager::vFlush()
|
||||
// save the shaders
|
||||
char strfile[255];
|
||||
sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
|
||||
std::ofstream fps(strfile);
|
||||
std::ofstream fps;
|
||||
OpenFStream(fps, strfile, std::ios_base::out);
|
||||
fps << ps->strprog.c_str();
|
||||
sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
|
||||
std::ofstream fvs(strfile);
|
||||
std::ofstream fvs;
|
||||
OpenFStream(fvs, strfile, std::ios_base::out);
|
||||
fvs << vs->strprog.c_str();
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,8 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
|
||||
static int num_failures = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file(szTemp);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, szTemp, std::ios_base::out);
|
||||
file << pstrprogram;
|
||||
file.close();
|
||||
|
||||
|
@ -92,6 +92,7 @@ Make AA apply instantly during gameplay if possible
|
||||
#include "FramebufferManager.h"
|
||||
#include "Core.h"
|
||||
#include "Host.h"
|
||||
#include "PerfQuery.h"
|
||||
|
||||
#include "VideoState.h"
|
||||
#include "VideoBackend.h"
|
||||
@ -194,6 +195,7 @@ void VideoBackend::Video_Prepare()
|
||||
|
||||
BPInit();
|
||||
g_vertex_manager = new VertexManager;
|
||||
g_perf_query = new PerfQuery;
|
||||
Fifo_Init(); // must be done before OpcodeDecoder_Init()
|
||||
OpcodeDecoder_Init();
|
||||
VertexShaderCache::Init();
|
||||
@ -204,7 +206,9 @@ void VideoBackend::Video_Prepare()
|
||||
GL_REPORT_ERRORD();
|
||||
VertexLoaderManager::Init();
|
||||
TextureConverter::Init();
|
||||
#ifndef _M_GENERIC
|
||||
DLCache::Init();
|
||||
#endif
|
||||
|
||||
// Notify the core that the video backend is ready
|
||||
Host_Message(WM_USER_CREATE);
|
||||
@ -219,7 +223,9 @@ void VideoBackend::Shutdown()
|
||||
s_efbAccessRequested = false;
|
||||
s_FifoShuttingDown = false;
|
||||
s_swapRequested = false;
|
||||
#ifndef _M_GENERIC
|
||||
DLCache::Shutdown();
|
||||
#endif
|
||||
Fifo_Shutdown();
|
||||
PostProcessing::Shutdown();
|
||||
|
||||
|
Reference in New Issue
Block a user