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:
NeoBrainX 2010-11-29 16:16:48 +00:00
parent 40c4e5f9a7
commit 8d123adf64
11 changed files with 173 additions and 30 deletions

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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

View File

@ -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";
}

View File

@ -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);
};

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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";
}

View File

@ -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

View File

@ -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);
}