d3d12: PSO caching works

This commit is contained in:
vlj 2015-05-11 18:38:57 +02:00 committed by Vincent Lejeune
parent 0ebc221011
commit e58292bb11
4 changed files with 42 additions and 80 deletions

View file

@ -211,7 +211,7 @@ bool D3D12GSRender::LoadProgram()
return false; return false;
} }
m_PSO = new D3D12PipelineState(m_device, m_cur_vertex_prog, m_cur_fragment_prog); m_PSO = getGraphicPipelineState(m_device, m_cur_vertex_prog, m_cur_fragment_prog);
return true; return true;
} }
@ -226,7 +226,7 @@ void D3D12GSRender::ExecCMD()
InitDrawBuffers(); InitDrawBuffers();
ID3D12CommandList *commandList; // ID3D12CommandList *commandList;
// m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList)); // m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
/* if (m_set_color_mask) /* if (m_set_color_mask)

View file

@ -47,7 +47,7 @@ private:
// std::vector<u8> m_vdata; // std::vector<u8> m_vdata;
// std::vector<PostDrawObj> m_post_draw_objs; // std::vector<PostDrawObj> m_post_draw_objs;
D3D12PipelineState *m_PSO; ID3D12PipelineState *m_PSO;
int m_fp_buf_num; int m_fp_buf_num;
int m_vp_buf_num; int m_vp_buf_num;
// GLProgramBuffer m_prog_buffer; // GLProgramBuffer m_prog_buffer;

View file

@ -41,6 +41,7 @@ public:
Shader() : bytecode(nullptr) {} Shader() : bytecode(nullptr) {}
~Shader() {} ~Shader() {}
u32 Id;
Microsoft::WRL::ComPtr<ID3DBlob> bytecode; Microsoft::WRL::ComPtr<ID3DBlob> bytecode;
std::vector<u8> RSXBinary; std::vector<u8> RSXBinary;
@ -198,13 +199,21 @@ struct FragmentProgramCompare
typedef std::unordered_map<void *, Shader, HashVertexProgram, VertexProgramCompare> binary2VS; typedef std::unordered_map<void *, Shader, HashVertexProgram, VertexProgramCompare> binary2VS;
typedef std::unordered_map<void *, Shader, HashFragmentProgram, FragmentProgramCompare> binary2FS; typedef std::unordered_map<void *, Shader, HashFragmentProgram, FragmentProgramCompare> binary2FS;
static int tmp = 0;
class ProgramBuffer class ProgramBuffer
{ {
public: public:
binary2VS cacheVS; binary2VS cacheVS;
binary2FS cacheFS; binary2FS cacheFS;
// Key is vertex << 32 | fragment ids
std::unordered_map<u64, ID3D12PipelineState *> cachePSO;
size_t currentShaderId;
ProgramBuffer() : currentShaderId(0)
{}
bool SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader) bool SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader)
{ {
binary2FS::const_iterator It = cacheFS.find(vm::get_ptr<void>(rsx_fp.addr)); binary2FS::const_iterator It = cacheFS.find(vm::get_ptr<void>(rsx_fp.addr));
@ -227,78 +236,45 @@ public:
return false; return false;
} }
/* ID3D12PipelineState *GetProg(u32 fp, u32 vp) const ID3D12PipelineState *GetProg(u32 fp, u32 vp) const
{ {
if (fp == vp) u64 key = vp << 32 | fp;
{*/ std::unordered_map<u64, ID3D12PipelineState *>::const_iterator It = cachePSO.find(key);
/* if (It == cachePSO.end())
LOG_NOTICE(RSX, "Get program (%d):", fp); return nullptr;
LOG_NOTICE(RSX, "*** prog id = %d", m_buf[fp].prog_id); return It->second;
LOG_NOTICE(RSX, "*** vp id = %d", m_buf[fp].vp_id);
LOG_NOTICE(RSX, "*** fp id = %d", m_buf[fp].fp_id);
LOG_NOTICE(RSX, "*** vp shader = \n%s", m_buf[fp].vp_shader.wx_str());
LOG_NOTICE(RSX, "*** fp shader = \n%s", m_buf[fp].fp_shader.wx_str());
*/
/* return m_buf[fp].prog_id;
} }
for (u32 i = 0; i<m_buf.size(); ++i) void AddVertexProgram(Shader& vp, RSXVertexProgram& rsx_vp)
{
if (i == fp || i == vp) continue;*/
// if (CmpVP(vp, i) && CmpFP(fp, i))
// {
/*
LOG_NOTICE(RSX, "Get program (%d):", i);
LOG_NOTICE(RSX, "*** prog id = %d", m_buf[i].prog_id);
LOG_NOTICE(RSX, "*** vp id = %d", m_buf[i].vp_id);
LOG_NOTICE(RSX, "*** fp id = %d", m_buf[i].fp_id);
LOG_NOTICE(RSX, "*** vp shader = \n%s", m_buf[i].vp_shader.wx_str());
LOG_NOTICE(RSX, "*** fp shader = \n%s", m_buf[i].fp_shader.wx_str());
*/
/* return m_buf[i].prog_id;
}
}
return 0;
}*/
void AddVertexProgram(const Shader& vp, RSXVertexProgram& rsx_vp)
{ {
size_t actualVPSize = rsx_vp.data.size() * 4; size_t actualVPSize = rsx_vp.data.size() * 4;
void *fpShadowCopy = malloc(actualVPSize); void *fpShadowCopy = malloc(actualVPSize);
memcpy(fpShadowCopy, rsx_vp.data.data(), actualVPSize); memcpy(fpShadowCopy, rsx_vp.data.data(), actualVPSize);
vp.Id = currentShaderId++;
cacheVS.insert(std::make_pair(fpShadowCopy, vp)); cacheVS.insert(std::make_pair(fpShadowCopy, vp));
} }
void AddFragmentProgram(const Shader& fp, RSXFragmentProgram& rsx_fp) void AddFragmentProgram(Shader& fp, RSXFragmentProgram& rsx_fp)
{ {
size_t actualFPSize = getFPBinarySize(vm::get_ptr<u8>(rsx_fp.addr)); size_t actualFPSize = getFPBinarySize(vm::get_ptr<u8>(rsx_fp.addr));
void *fpShadowCopy = malloc(actualFPSize); void *fpShadowCopy = malloc(actualFPSize);
memcpy(fpShadowCopy, vm::get_ptr<u8>(rsx_fp.addr), actualFPSize); memcpy(fpShadowCopy, vm::get_ptr<u8>(rsx_fp.addr), actualFPSize);
fp.Id = currentShaderId++;
cacheFS.insert(std::make_pair(fpShadowCopy, fp)); cacheFS.insert(std::make_pair(fpShadowCopy, fp));
} }
void Add(ID3D12PipelineState *prog, Shader& fp, RSXFragmentProgram& rsx_fp, Shader& vp, RSXVertexProgram& rsx_vp) void Add(ID3D12PipelineState *prog, Shader& fp, Shader& vp)
{ {
/* LOG_NOTICE(RSX, "Add program (%d):", m_buf.size()); u64 key = vp.Id << 32 | fp.Id;
LOG_NOTICE(RSX, "*** prog id = %x", prog); cachePSO.insert(std::make_pair(key, prog));
LOG_NOTICE(RSX, "*** vp id = %d", vp.id);
LOG_NOTICE(RSX, "*** fp id = %d", fp.id);
LOG_NOTICE(RSX, "*** vp data size = %d", rsx_vp.data.size() * 4);
LOG_NOTICE(RSX, "*** fp data size = %d", rsx_fp.size);
LOG_NOTICE(RSX, "*** vp shader = \n%s", vp.shader.c_str());
LOG_NOTICE(RSX, "*** fp shader = \n%s", fp.shader.c_str());*/
} }
}; };
static ProgramBuffer g_cachedProgram; static ProgramBuffer g_cachedProgram;
D3D12PipelineState::D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader) ID3D12PipelineState *getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader)
{ {
ID3D12PipelineState *result = nullptr;
Shader m_vertex_prog, m_fragment_prog; Shader m_vertex_prog, m_fragment_prog;
bool m_fp_buf_num = g_cachedProgram.SearchFp(*fragmentShader, m_fragment_prog); bool m_fp_buf_num = g_cachedProgram.SearchFp(*fragmentShader, m_fragment_prog);
bool m_vp_buf_num = g_cachedProgram.SearchVp(*vertexShader, m_vertex_prog); bool m_vp_buf_num = g_cachedProgram.SearchVp(*vertexShader, m_vertex_prog);
@ -325,13 +301,12 @@ D3D12PipelineState::D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *v
// fs::file("./VertexProgram.txt", o_write | o_create | o_trunc).write(m_vertex_prog.shader.c_str(), m_vertex_prog.shader.size()); // fs::file("./VertexProgram.txt", o_write | o_create | o_trunc).write(m_vertex_prog.shader.c_str(), m_vertex_prog.shader.size());
} }
// if (m_fp_buf_num != -1 && m_vp_buf_num != -1) if (m_fp_buf_num && m_vp_buf_num)
{ result = g_cachedProgram.GetProg(m_fragment_prog.Id, m_vertex_prog.Id);
// m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num);
}
if (false)//m_program.id) if (result != nullptr)
{ {
return result;
/* // RSX Debugger: Check if this program was modified and update it /* // RSX Debugger: Check if this program was modified and update it
if (Ini.GSLogPrograms.GetValue()) if (Ini.GSLogPrograms.GetValue())
{ {
@ -364,22 +339,21 @@ D3D12PipelineState::D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *v
} }
else else
{ {
LOG_WARNING(RSX, "Add program :");
LOG_WARNING(RSX, "*** vp id = %d", m_vertex_prog.Id);
LOG_WARNING(RSX, "*** fp id = %d", m_fragment_prog.Id);
D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {}; D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {};
/* graphicPipelineStateDesc.VS.BytecodeLength = m_vertex_prog.bytecode->GetBufferSize(); graphicPipelineStateDesc.VS.BytecodeLength = m_vertex_prog.bytecode->GetBufferSize();
graphicPipelineStateDesc.VS.pShaderBytecode = m_vertex_prog.bytecode->GetBufferPointer(); graphicPipelineStateDesc.VS.pShaderBytecode = m_vertex_prog.bytecode->GetBufferPointer();
graphicPipelineStateDesc.PS.BytecodeLength = m_fragment_prog.bytecode->GetBufferSize(); graphicPipelineStateDesc.PS.BytecodeLength = m_fragment_prog.bytecode->GetBufferSize();
graphicPipelineStateDesc.PS.pShaderBytecode = m_fragment_prog.bytecode->GetBufferPointer(); graphicPipelineStateDesc.PS.pShaderBytecode = m_fragment_prog.bytecode->GetBufferPointer();
device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&m_pipelineStateObject));*/ device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result));
g_cachedProgram.Add(m_pipelineStateObject, m_fragment_prog, *fragmentShader, m_vertex_prog, *vertexShader); g_cachedProgram.Add(result, m_fragment_prog, m_vertex_prog);
/*m_program.Create(m_vertex_prog.id, m_fragment_prog.id);
checkForGlError("m_program.Create");
m_prog_buffer.Add(m_program, m_fragment_prog, *m_cur_fragment_prog, m_vertex_prog, *m_cur_vertex_prog);
checkForGlError("m_prog_buffer.Add");
m_program.Use();
// RSX Debugger // RSX Debugger
if (Ini.GSLogPrograms.GetValue()) /*if (Ini.GSLogPrograms.GetValue())
{ {
RSXDebuggerProgram program; RSXDebuggerProgram program;
program.id = m_program.id; program.id = m_program.id;
@ -392,10 +366,5 @@ D3D12PipelineState::D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *v
} }
} }
D3D12PipelineState::~D3D12PipelineState()
{
}
#endif #endif

View file

@ -5,13 +5,6 @@
#include "Emu/RSX/RSXFragmentProgram.h" #include "Emu/RSX/RSXFragmentProgram.h"
#include "Emu/RSX/RSXVertexProgram.h" #include "Emu/RSX/RSXVertexProgram.h"
class D3D12PipelineState ID3D12PipelineState *getGraphicPipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader);
{
ID3D12PipelineState *m_pipelineStateObject;
ID3D12RootSignature *m_rootSignature;
public:
D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader);
~D3D12PipelineState();
};
#endif #endif