DX9 debugger improvements:
- Fix "Pause at next" functionality for pixel/vertex shader changes, finished frames and texture changes. - Implement dumping vertex declaration and vertex/index data. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6496 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
40c4e5f9a7
commit
8d123adf64
|
@ -39,6 +39,11 @@ public:
|
|||
|
||||
virtual ::NativeVertexFormat* CreateNativeVertexFormat() = 0;
|
||||
|
||||
static u16* GetTriangleIndexBuffer() { return TIBuffer; }
|
||||
static u16* GetLineIndexBuffer() { return LIBuffer; }
|
||||
static u16* GetPointIndexBuffer() { return PIBuffer; }
|
||||
static u8* GetVertexBuffer() { return LocalVBuffer; }
|
||||
|
||||
protected:
|
||||
// TODO: make private after Flush() is merged
|
||||
static void ResetBuffer();
|
||||
|
|
|
@ -21,14 +21,17 @@
|
|||
#include "FileUtil.h"
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "../Globals.h"
|
||||
#include "../D3DBase.h"
|
||||
#include "../FramebufferManager.h"
|
||||
#include "../TextureCache.h"
|
||||
#include "../VertexShaderCache.h"
|
||||
#include "../PixelShaderCache.h"
|
||||
#include "../VertexManager.h"
|
||||
|
||||
extern int g_Preset;
|
||||
extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
BEGIN_EVENT_TABLE(GFXDebuggerDX9, wxPanel)
|
||||
EVT_CLOSE(GFXDebuggerDX9::OnClose)
|
||||
|
@ -313,39 +316,36 @@ void GFXDebuggerDX9::OnPauseAtNextFrameButton(wxCommandEvent& event)
|
|||
|
||||
void GFXDebuggerDX9::OnDumpButton(wxCommandEvent& event)
|
||||
{
|
||||
char dump_path[MAX_PATH];
|
||||
sprintf(dump_path, "%sDebug/%s", File::GetUserPath(D_DUMP_IDX), globals->unique_id);
|
||||
if (!File::Exists(dump_path) || !File::IsDirectory(dump_path))
|
||||
if (!File::CreateDir(dump_path))
|
||||
return;
|
||||
|
||||
switch (m_pDumpList->GetSelection())
|
||||
{
|
||||
case 0: // Pixel Shader
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/Debug/%s/dump_ps.txt", File::GetUserPath(D_DUMP_IDX), globals->unique_id);
|
||||
sprintf(filename, "%s/dump_ps.txt", dump_path);
|
||||
File::CreateEmptyFile(filename);
|
||||
File::WriteStringToFile(true, PixelShaderCache::GetCurrentShaderCode(), filename);
|
||||
#else
|
||||
MessageBox(NULL, L"Dumping pixel shaders not supported in Release builds!", L"Error", MB_OK);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // Vertex Shader
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/Debug/%s/dump_vs.txt", File::GetUserPath(D_DUMP_IDX), globals->unique_id);
|
||||
sprintf(filename, "%s/dump_vs.txt", dump_path);
|
||||
File::CreateEmptyFile(filename);
|
||||
File::WriteStringToFile(true, VertexShaderCache::GetCurrentShaderCode(), filename);
|
||||
#else
|
||||
MessageBox(NULL, L"Dumping vertex shaders not supported in Release builds!", L"Error", MB_OK);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // Pixel Shader Constants
|
||||
{
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/Debug/%s/dump_ps_consts.txt", File::GetUserPath(D_DUMP_IDX), globals->unique_id);
|
||||
|
||||
sprintf(filename, "%s/dump_ps_consts.txt", dump_path);
|
||||
FILE* file = fopen(filename, "w");
|
||||
|
||||
float constants[4*C_PENVCONST_END];
|
||||
|
@ -379,14 +379,13 @@ void GFXDebuggerDX9::OnDumpButton(wxCommandEvent& event)
|
|||
fprintf(file, "Constant COLORMATRIX %d: %f %f %f %f\n", i, constants[4*i], constants[4*i+1], constants[4*i+2], constants[4*i+3]);
|
||||
|
||||
fclose(file);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: // Vertex Shader Constants
|
||||
{
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/Debug/%s/dump_vs_consts.txt", File::GetUserPath(D_DUMP_IDX), globals->unique_id);
|
||||
sprintf(filename, "%s/dump_vs_consts.txt", dump_path);
|
||||
FILE* file = fopen(filename, "w");
|
||||
|
||||
float constants[4*C_VENVCONST_END];
|
||||
|
@ -437,7 +436,7 @@ void GFXDebuggerDX9::OnDumpButton(wxCommandEvent& event)
|
|||
D3D::dev->GetTexture(stage, (IDirect3DBaseTexture9**)&texture);
|
||||
if(!texture) break;
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/Debug/%s/dump_tex%d.png", File::GetUserPath(D_DUMP_IDX), globals->unique_id, stage);
|
||||
sprintf(filename, "%s/dump_tex%d.png", dump_path, stage);
|
||||
IDirect3DSurface9* surface;
|
||||
texture->GetSurfaceLevel(0, &surface);
|
||||
HRESULT hr = PD3DXSaveSurfaceToFileA(filename, D3DXIFF_PNG, surface, NULL, NULL);
|
||||
|
@ -453,17 +452,131 @@ void GFXDebuggerDX9::OnDumpButton(wxCommandEvent& event)
|
|||
break;
|
||||
|
||||
case 13: // Vertices
|
||||
{
|
||||
D3DVERTEXELEMENT9* elements;
|
||||
int num_elements;
|
||||
((DX9::VertexManager*)g_vertex_manager)->GetElements(g_nativeVertexFmt, &elements, &num_elements);
|
||||
if (elements == NULL || num_elements == 0)
|
||||
return;
|
||||
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/vertex_dump.txt", dump_path);
|
||||
FILE* file = fopen(filename, "w");
|
||||
|
||||
u8* vertices = g_vertex_manager->GetVertexBuffer();
|
||||
u16* tri_indices = g_vertex_manager->GetTriangleIndexBuffer();
|
||||
u16* line_indices = g_vertex_manager->GetLineIndexBuffer();
|
||||
u16* point_indices = g_vertex_manager->GetPointIndexBuffer();
|
||||
|
||||
fprintf(file, "VERTICES\n");
|
||||
for (int i = 0; i < IndexGenerator::GetNumVerts(); ++i)
|
||||
{
|
||||
u8* cur_vertex = vertices + i * g_nativeVertexFmt->GetVertexStride();
|
||||
for (int elem = 0; elem < num_elements; elem++)
|
||||
{
|
||||
switch (elements[elem].Type)
|
||||
{
|
||||
case D3DDECLTYPE_FLOAT1:
|
||||
fprintf(file, "%f\t", *(float*)&cur_vertex[elements[elem].Offset]);
|
||||
break;
|
||||
case D3DDECLTYPE_FLOAT2:
|
||||
fprintf(file, "%f ", *(float*)&cur_vertex[elements[elem].Offset]);
|
||||
fprintf(file, "%f\t", *(float*)&cur_vertex[4+elements[elem].Offset]);
|
||||
break;
|
||||
case D3DDECLTYPE_FLOAT3:
|
||||
fprintf(file, "%f ", *(float*)&cur_vertex[elements[elem].Offset]);
|
||||
fprintf(file, "%f ", *(float*)&cur_vertex[4+elements[elem].Offset]);
|
||||
fprintf(file, "%f\t", *(float*)&cur_vertex[8+elements[elem].Offset]);
|
||||
break;
|
||||
case D3DDECLTYPE_FLOAT4:
|
||||
fprintf(file, "%f ", *(float*)&cur_vertex[elements[elem].Offset]);
|
||||
fprintf(file, "%f ", *(float*)&cur_vertex[4+elements[elem].Offset]);
|
||||
fprintf(file, "%f ", *(float*)&cur_vertex[8+elements[elem].Offset]);
|
||||
fprintf(file, "%f\t", *(float*)&cur_vertex[12+elements[elem].Offset]);
|
||||
break;
|
||||
case D3DDECLTYPE_UBYTE4N:
|
||||
fprintf(file, "%f ", (float)(*(u8*)&cur_vertex[elements[elem].Offset])/255.f);
|
||||
fprintf(file, "%f ", (float)(*(u8*)&cur_vertex[1+elements[elem].Offset])/255.f);
|
||||
fprintf(file, "%f ", (float)(*(u8*)&cur_vertex[2+elements[elem].Offset])/255.f);
|
||||
fprintf(file, "%f\t", (float)(*(u8*)&cur_vertex[3+elements[elem].Offset])/255.f);
|
||||
break;
|
||||
case D3DDECLTYPE_SHORT2N:
|
||||
fprintf(file, "%f ", (float)(*(s16*)&cur_vertex[elements[elem].Offset])/32767.f);
|
||||
fprintf(file, "%f\t", (float)(*(s16*)&cur_vertex[2+elements[elem].Offset])/32767.f);
|
||||
break;
|
||||
case D3DDECLTYPE_SHORT4N:
|
||||
fprintf(file, "%f ", (float)(*(s16*)&cur_vertex[elements[elem].Offset])/32767.f);
|
||||
fprintf(file, "%f ", (float)(*(s16*)&cur_vertex[2+elements[elem].Offset])/32767.f);
|
||||
fprintf(file, "%f ", (float)(*(s16*)&cur_vertex[4+elements[elem].Offset])/32767.f);
|
||||
fprintf(file, "%f\t", (float)(*(s16*)&cur_vertex[6+elements[elem].Offset])/32767.f);
|
||||
break;
|
||||
case D3DDECLTYPE_USHORT2N:
|
||||
fprintf(file, "%f ", (float)(*(u16*)&cur_vertex[elements[elem].Offset])/65535.f);
|
||||
fprintf(file, "%f\t", (float)(*(u16*)&cur_vertex[2+elements[elem].Offset])/65535.f);
|
||||
break;
|
||||
case D3DDECLTYPE_USHORT4N:
|
||||
fprintf(file, "%f ", (float)(*(u16*)&cur_vertex[elements[elem].Offset])/65535.f);
|
||||
fprintf(file, "%f ", (float)(*(u16*)&cur_vertex[2+elements[elem].Offset])/65535.f);
|
||||
fprintf(file, "%f ", (float)(*(u16*)&cur_vertex[4+elements[elem].Offset])/65535.f);
|
||||
fprintf(file, "%f\t", (float)(*(u16*)&cur_vertex[6+elements[elem].Offset])/65535.f);
|
||||
break;
|
||||
}
|
||||
fprintf(file, "\t");
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
fprintf(file, "\nTRIANGLE INDICES\n");
|
||||
for (int i = 0; i < IndexGenerator::GetNumTriangles(); ++i)
|
||||
fprintf(file, "%d\t%d\t%d\n", tri_indices[3*i], tri_indices[3*i+1], tri_indices[3*i+2]);
|
||||
|
||||
fprintf(file, "\nLINE INDICES\n");
|
||||
for (int i = 0; i < IndexGenerator::GetNumLines(); ++i)
|
||||
fprintf(file, "%d\t%d\n", line_indices[2*i], line_indices[2*i+1]);
|
||||
|
||||
fprintf(file, "\nPOINT INDICES\n");
|
||||
for (int i = 0; i < IndexGenerator::GetNumPoints(); ++i)
|
||||
fprintf(file, "%d\n", point_indices[i]);
|
||||
|
||||
fclose(file);
|
||||
break;
|
||||
}
|
||||
|
||||
case 14: // Vertex Description
|
||||
break;
|
||||
{
|
||||
D3DVERTEXELEMENT9* elements;
|
||||
int num_elements;
|
||||
((DX9::VertexManager*)g_vertex_manager)->GetElements(g_nativeVertexFmt, &elements, &num_elements);
|
||||
if (elements == NULL || num_elements == 0)
|
||||
return;
|
||||
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "%s/vertex_decl.txt", dump_path);
|
||||
FILE* file = fopen(filename, "w");
|
||||
|
||||
fprintf(file, "Index\tOffset\tType\t\tUsage\t\tUsageIndex\n");
|
||||
for (int i = 0; i < num_elements; ++i)
|
||||
{
|
||||
const char* types[] = {
|
||||
"FLOAT1 " , "FLOAT2 ", "FLOAT3 ", "FLOAT4 ", "D3DCOLOR", "UBYTE4 ", "SHORT2 ", "SHORT4 ",
|
||||
"UBYTE4N " , "SHORT2N ", "SHORT4N ", "USHORT2N", "USHORT4N", "UDEC3 ", "DEC3N ", "FLOAT16_2",
|
||||
"FLOAT16_4", "UNUSED ",
|
||||
};
|
||||
const char* usages[] = {
|
||||
"POSITION ", "BLENDWEIGHT ", "BLENDINDICES", "NORMAL ", "PSIZE ", "TEXCOORD ", "TANGENT ", "BINORMAL ",
|
||||
"TESSFACTOR ", "POSITIONT ", "COLOR ", "FOG ", "DEPTH ", "SAMPLE ",
|
||||
};
|
||||
fprintf(file, "%d\t%d\t%s\t%s\t%d\n", i, elements[i].Offset, types[elements[i].Type], usages[elements[i].Usage], elements[i].UsageIndex);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
break;
|
||||
}
|
||||
case 15: // Vertex Matrices
|
||||
break;
|
||||
|
||||
case 16: // Statistics
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ public:
|
|||
~D3DVertexFormat();
|
||||
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
virtual void SetupVertexPointers() const;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
D3DVERTEXELEMENT9 elements[32];
|
||||
int num_elements;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace DX9
|
||||
|
@ -49,6 +54,17 @@ NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
|
|||
|
||||
}
|
||||
|
||||
void DX9::VertexManager::GetElements(NativeVertexFormat* format, D3DVERTEXELEMENT9** elems, int* num)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
*elems = ((D3DVertexFormat*)format)->elements;
|
||||
*num = ((D3DVertexFormat*)format)->num_elements;
|
||||
#else
|
||||
*elems = NULL;
|
||||
*num = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
D3DVertexFormat::~D3DVertexFormat()
|
||||
{
|
||||
if (d3d_decl)
|
||||
|
@ -163,6 +179,10 @@ void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
|||
PanicAlert("Failed to create D3D vertex declaration!");
|
||||
return;
|
||||
}
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
memcpy(&elements, elems, sizeof(elems));
|
||||
num_elements = elem_idx;
|
||||
#endif
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers() const
|
||||
|
|
|
@ -352,6 +352,8 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
|||
}
|
||||
#endif
|
||||
delete [] bytecode;
|
||||
|
||||
DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -381,12 +383,12 @@ bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytec
|
|||
}
|
||||
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string PixelShaderCache::GetCurrentShaderCode()
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (last_entry)
|
||||
return last_entry->code;
|
||||
else
|
||||
return "(no shader)\n";
|
||||
}
|
||||
#endif
|
||||
return "(not available)\n";
|
||||
}
|
||||
|
|
|
@ -67,10 +67,7 @@ public:
|
|||
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
static std::string GetCurrentShaderCode();
|
||||
#endif
|
||||
static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1097,6 +1097,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
|||
|
||||
OSD::DrawMessages();
|
||||
D3D::EndFrame();
|
||||
|
||||
DEBUGGER_PAUSE_AT(NEXT_FRAME,true);
|
||||
|
||||
frameCount++;
|
||||
DLCache::ProgressiveCleanup();
|
||||
TextureCache::Cleanup();
|
||||
|
|
|
@ -66,6 +66,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[])
|
|||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
||||
{
|
||||
DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE,true);
|
||||
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
||||
// D3D9 will automatically generate mip maps if necessary
|
||||
}
|
||||
|
@ -214,6 +215,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, u
|
|||
entry->swap_r_b = swap_r_b;
|
||||
entry->d3d_fmt = d3d_fmt;
|
||||
|
||||
DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE,true);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ namespace DX9
|
|||
|
||||
class VertexManager : public ::VertexManager
|
||||
{
|
||||
public:
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
void GetElements(NativeVertexFormat* format, D3DVERTEXELEMENT9** elems, int* num);
|
||||
|
||||
private:
|
||||
void Draw(int stride);
|
||||
|
|
|
@ -260,6 +260,7 @@ bool VertexShaderCache::SetShader(u32 components)
|
|||
}
|
||||
#endif
|
||||
delete [] bytecode;
|
||||
DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE,true);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -286,12 +287,12 @@ bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *byt
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string VertexShaderCache::GetCurrentShaderCode()
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (last_entry)
|
||||
return last_entry->code;
|
||||
else
|
||||
return "(no shader)\n";
|
||||
}
|
||||
#endif
|
||||
return "(not available)\n";
|
||||
}
|
||||
|
|
|
@ -58,10 +58,8 @@ public:
|
|||
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
|
||||
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
|
||||
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
|
||||
static std::string GetCurrentShaderCode();
|
||||
#endif
|
||||
static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram);
|
||||
};
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H
|
||||
|
|
|
@ -180,7 +180,7 @@ void DllConfig(void *_hParent)
|
|||
{
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter);
|
||||
|
||||
for (int i = 0; i < adapter.aa_levels.size(); ++i)
|
||||
for (int i = 0; i < (int)adapter.aa_levels.size(); ++i)
|
||||
g_Config.backend_info.AAModes.push_back(adapter.aa_levels[i].name);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue