d3d12: cache PSO State too

This commit is contained in:
vlj 2015-05-13 22:24:53 +02:00 committed by Vincent Lejeune
parent da5b047c58
commit 75219be066
3 changed files with 62 additions and 18 deletions

View File

@ -457,7 +457,10 @@ bool D3D12GSRender::LoadProgram()
return false;
}
m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_rootSignature, m_cur_vertex_prog, m_cur_fragment_prog, m_IASet);
PipelineProperties prop = {};
prop.Topology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_rootSignature, m_cur_vertex_prog, m_cur_fragment_prog, prop, m_IASet);
return m_PSO != nullptr;
}

View File

@ -58,11 +58,9 @@ bool PipelineStateObjectCache::SearchVp(const RSXVertexProgram& rsx_vp, Shader&
return false;
}
ID3D12PipelineState *PipelineStateObjectCache::GetProg(u32 fp, u32 vp) const
ID3D12PipelineState *PipelineStateObjectCache::GetProg(const PSOKey &key) const
{
u64 vpLong = vp;
u64 key = vpLong << 32 | fp;
std::unordered_map<u64, ID3D12PipelineState *>::const_iterator It = m_cachePSO.find(key);
std::unordered_map<PSOKey, ID3D12PipelineState *, PSOKeyHash, PSOKeyCompare>::const_iterator It = m_cachePSO.find(key);
if (It == m_cachePSO.end())
return nullptr;
return It->second;
@ -86,14 +84,18 @@ void PipelineStateObjectCache::AddFragmentProgram(Shader& fp, RSXFragmentProgram
m_cacheFS.insert(std::make_pair(fpShadowCopy, fp));
}
void PipelineStateObjectCache::Add(ID3D12PipelineState *prog, Shader& fp, Shader& vp)
void PipelineStateObjectCache::Add(ID3D12PipelineState *prog, const PSOKey& PSOKey)
{
u64 vpLong = vp.Id;
u64 key = vpLong << 32 | fp.Id;
m_cachePSO.insert(std::make_pair(key, prog));
m_cachePSO.insert(std::make_pair(PSOKey, prog));
}
ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Device *device, ID3D12RootSignature *rootSignature, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet)
ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(
ID3D12Device *device,
ID3D12RootSignature *rootSignature,
RSXVertexProgram *vertexShader,
RSXFragmentProgram *fragmentShader,
const PipelineProperties &pipelineProperties,
const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet)
{
ID3D12PipelineState *result = nullptr;
Shader m_vertex_prog, m_fragment_prog;
@ -123,7 +125,9 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev
}
if (m_fp_buf_num && m_vp_buf_num)
result = GetProg(m_fragment_prog.Id, m_vertex_prog.Id);
{
result = GetProg({ m_vertex_prog.Id, m_fragment_prog.Id, pipelineProperties });
}
if (result != nullptr)
{
@ -221,7 +225,7 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev
graphicPipelineStateDesc.BlendState = CD3D12_BLEND_DESC;
graphicPipelineStateDesc.DepthStencilState = CD3D12_DEPTH_STENCIL_DESC;
graphicPipelineStateDesc.RasterizerState = CD3D12_RASTERIZER_DESC;
graphicPipelineStateDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
graphicPipelineStateDesc.PrimitiveTopologyType = pipelineProperties.Topology;
graphicPipelineStateDesc.NumRenderTargets = 1;
graphicPipelineStateDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
@ -234,7 +238,7 @@ ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState(ID3D12Dev
graphicPipelineStateDesc.NodeMask = 1;
device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result));
Add(result, m_fragment_prog, m_vertex_prog);
Add(result, {m_vertex_prog.Id, m_fragment_prog.Id, pipelineProperties });
// RSX Debugger
/*if (Ini.GSLogPrograms.GetValue())

View File

@ -13,6 +13,11 @@ enum class SHADER_TYPE
SHADER_TYPE_FRAGMENT
};
struct PipelineProperties
{
D3D12_PRIMITIVE_TOPOLOGY_TYPE Topology;
};
/** Storage for a shader
* Embeds the D3DBlob corresponding to
*/
@ -139,6 +144,31 @@ struct FragmentProgramCompare
typedef std::unordered_map<void *, Shader, HashVertexProgram, VertexProgramCompare> binary2VS;
typedef std::unordered_map<void *, Shader, HashFragmentProgram, FragmentProgramCompare> binary2FS;
struct PSOKey
{
u32 vpIdx;
u32 fpIdx;
PipelineProperties properties;
};
struct PSOKeyHash
{
size_t operator()(const PSOKey &key) const
{
size_t hashValue = 0;
hashValue ^= std::hash<unsigned>()(key.vpIdx);
return hashValue;
}
};
struct PSOKeyCompare
{
size_t operator()(const PSOKey &key1, const PSOKey &key2) const
{
return (key1.vpIdx == key2.vpIdx) && (key1.fpIdx == key2.fpIdx) && (key1.properties.Topology == key2.properties.Topology);
}
};
/**
* Cache for shader blobs and Pipeline state object
* The class is responsible for creating the object so the state only has to call getGraphicPipelineState
@ -149,20 +179,27 @@ private:
size_t m_currentShaderId;
binary2VS m_cacheVS;
binary2FS m_cacheFS;
// Key is vertex << 32 | fragment ids
std::unordered_map<u64, ID3D12PipelineState *> m_cachePSO;
std::unordered_map<PSOKey, ID3D12PipelineState *, PSOKeyHash, PSOKeyCompare> m_cachePSO;
bool SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader);
bool SearchVp(const RSXVertexProgram& rsx_vp, Shader& shader);
ID3D12PipelineState *GetProg(u32 fp, u32 vp) const;
ID3D12PipelineState *GetProg(const PSOKey &psoKey) const;
void AddVertexProgram(Shader& vp, RSXVertexProgram& rsx_vp);
void AddFragmentProgram(Shader& fp, RSXFragmentProgram& rsx_fp);
void Add(ID3D12PipelineState *prog, Shader& fp, Shader& vp);
void Add(ID3D12PipelineState *prog, const PSOKey& PSOKey);
public:
PipelineStateObjectCache();
~PipelineStateObjectCache();
// Note: the last param is not taken into account if the PSO is not regenerated
ID3D12PipelineState *getGraphicPipelineState(ID3D12Device *device, ID3D12RootSignature *rootSignature, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader, const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet);
ID3D12PipelineState *getGraphicPipelineState(
ID3D12Device *device,
ID3D12RootSignature *rootSignature,
RSXVertexProgram *vertexShader,
RSXFragmentProgram *fragmentShader,
const PipelineProperties &pipelineProperties,
const std::vector<D3D12_INPUT_ELEMENT_DESC> &IASet
);
};