From ba66992ee3bd06ad8e4cc42822329e9d8a805609 Mon Sep 17 00:00:00 2001 From: vlj Date: Fri, 15 May 2015 21:48:43 +0200 Subject: [PATCH] d3d12: Use template class for caching --- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 6 +- rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp | 269 -------------- rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h | 336 +++++++----------- .../RSX/D3D12/FragmentProgramDecompiler.cpp | 32 +- rpcs3/Emu/RSX/D3D12/ShaderParam.h | 22 +- .../Emu/RSX/D3D12/VertexProgramDecompiler.cpp | 34 +- 6 files changed, 172 insertions(+), 527 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 8cdac6a905..96a845b4dd 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -471,7 +471,7 @@ bool D3D12GSRender::LoadProgram() return false; } - PipelineProperties prop = {}; + D3D12PipelineProperties prop = {}; /* #define GL_POINTS 0x0000 #define GL_LINES 0x0001 @@ -504,8 +504,8 @@ bool D3D12GSRender::LoadProgram() prop.Topology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; } - - m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_rootSignature, m_cur_vertex_prog, m_cur_fragment_prog, prop, m_IASet); + prop.IASet = m_IASet; + m_PSO = m_cachePSO.getGraphicPipelineState(m_device, m_rootSignature, m_cur_vertex_prog, m_cur_fragment_prog, prop, std::make_pair(m_device, m_rootSignature)); return m_PSO != nullptr; } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index f968913911..6506826981 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -2,279 +2,10 @@ #if defined (DX12_SUPPORT) #include "D3D12PipelineState.h" -#include "Emu/Memory/vm.h" -#include "Utilities/Log.h" -#include #include -#include -#include "VertexProgramDecompiler.h" -#include "FragmentProgramDecompiler.h" -#include "Utilities/File.h" - -#include #pragma comment (lib, "d3dcompiler.lib") -namespace ProgramHashUtil -{ - - size_t getFPBinarySize(void *ptr) - { - const qword *instBuffer = (const qword*)ptr; - size_t instIndex = 0; - while (true) - { - const qword& inst = instBuffer[instIndex]; - bool isSRC0Constant = ((inst.word[1] >> 8) & 0x3) == 2; - bool isSRC1Constant = ((inst.word[2] >> 8) & 0x3) == 2; - bool isSRC2Constant = ((inst.word[3] >> 8) & 0x3) == 2; - bool end = (inst.word[0] >> 8) & 0x1; - - if (isSRC0Constant || isSRC1Constant || isSRC2Constant) - { - instIndex += 2; - if (end) - return instIndex * 4 * 4; - continue; - } - instIndex++; - if (end) - return (instIndex) * 4 * 4; - } - } -}; - - -PipelineStateObjectCache::PipelineStateObjectCache() : m_currentShaderId(0) -{} - -PipelineStateObjectCache::~PipelineStateObjectCache() -{ - for (auto pair : m_cachePSO) - pair.second->Release(); -} - -bool PipelineStateObjectCache::SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader) -{ - binary2FS::const_iterator It = m_cacheFS.find(vm::get_ptr(rsx_fp.addr)); - if (It != m_cacheFS.end()) - { - shader = It->second; - return true; - } - return false; -} - -bool PipelineStateObjectCache::SearchVp(const RSXVertexProgram& rsx_vp, Shader& shader) -{ - binary2VS::const_iterator It = m_cacheVS.find((void*)rsx_vp.data.data()); - if (It != m_cacheVS.end()) - { - shader = It->second; - return true; - } - return false; -} - -ID3D12PipelineState *PipelineStateObjectCache::GetProg(const PSOKey &key) const -{ - std::unordered_map::const_iterator It = m_cachePSO.find(key); - if (It == m_cachePSO.end()) - return nullptr; - return It->second; -} - -void PipelineStateObjectCache::AddVertexProgram(Shader& vp, RSXVertexProgram& rsx_vp) -{ - size_t actualVPSize = rsx_vp.data.size() * 4; - void *fpShadowCopy = malloc(actualVPSize); - memcpy(fpShadowCopy, rsx_vp.data.data(), actualVPSize); - vp.Id = (u32)m_currentShaderId++; - m_cacheVS.insert(std::make_pair(fpShadowCopy, vp)); -} - -void PipelineStateObjectCache::AddFragmentProgram(Shader& fp, RSXFragmentProgram& rsx_fp) -{ - size_t actualFPSize = ProgramHashUtil::getFPBinarySize(vm::get_ptr(rsx_fp.addr)); - void *fpShadowCopy = malloc(actualFPSize); - memcpy(fpShadowCopy, vm::get_ptr(rsx_fp.addr), actualFPSize); - fp.Id = (u32)m_currentShaderId++; - m_cacheFS.insert(std::make_pair(fpShadowCopy, fp)); -} - -void PipelineStateObjectCache::Add(ID3D12PipelineState *prog, const PSOKey& PSOKey) -{ - m_cachePSO.insert(std::make_pair(PSOKey, prog)); -} - -ID3D12PipelineState *PipelineStateObjectCache::getGraphicPipelineState( - ID3D12Device *device, - ID3D12RootSignature *rootSignature, - RSXVertexProgram *vertexShader, - RSXFragmentProgram *fragmentShader, - const PipelineProperties &pipelineProperties, - const std::vector &IASet) -{ - ID3D12PipelineState *result = nullptr; - Shader m_vertex_prog, m_fragment_prog; - bool m_fp_buf_num = SearchFp(*fragmentShader, m_fragment_prog); - bool m_vp_buf_num = SearchVp(*vertexShader, m_vertex_prog); - - if (!m_fp_buf_num) - { - LOG_WARNING(RSX, "FP not found in buffer!"); - FragmentDecompiler FS(fragmentShader->addr, fragmentShader->size, fragmentShader->offset); - const std::string &shader = FS.Decompile(); - m_fragment_prog.Compile(shader, SHADER_TYPE::SHADER_TYPE_FRAGMENT); - AddFragmentProgram(m_fragment_prog, *fragmentShader); - - // TODO: This shouldn't use current dir - fs::file("./FragmentProgram.hlsl", o_write | o_create | o_trunc).write(shader.c_str(), shader.size()); - } - - if (!m_vp_buf_num) - { - LOG_WARNING(RSX, "VP not found in buffer!"); - VertexDecompiler VS(vertexShader->data); - std::string shaderCode = VS.Decompile(); - m_vertex_prog.Compile(shaderCode, SHADER_TYPE::SHADER_TYPE_VERTEX); - AddVertexProgram(m_vertex_prog, *vertexShader); - - // TODO: This shouldn't use current dir - fs::file("./VertexProgram.hlsl", o_write | o_create | o_trunc).write(shaderCode.c_str(), shaderCode.size()); - } - - if (m_fp_buf_num && m_vp_buf_num) - { - result = GetProg({ m_vertex_prog.Id, m_fragment_prog.Id, pipelineProperties }); - } - - if (result != nullptr) - { - return result; - /* // RSX Debugger: Check if this program was modified and update it - if (Ini.GSLogPrograms.GetValue()) - { - for (auto& program : m_debug_programs) - { - if (program.id == m_program.id && program.modified) - { - // TODO: This isn't working perfectly. Is there any better/shorter way to update the program - m_vertex_prog.shader = program.vp_shader; - m_fragment_prog.shader = program.fp_shader; - m_vertex_prog.Wait(); - m_vertex_prog.Compile(); - checkForGlError("m_vertex_prog.Compile"); - m_fragment_prog.Wait(); - m_fragment_prog.Compile(); - checkForGlError("m_fragment_prog.Compile"); - glAttachShader(m_program.id, m_vertex_prog.id); - glAttachShader(m_program.id, m_fragment_prog.id); - glLinkProgram(m_program.id); - checkForGlError("glLinkProgram"); - glDetachShader(m_program.id, m_vertex_prog.id); - glDetachShader(m_program.id, m_fragment_prog.id); - program.vp_id = m_vertex_prog.id; - program.fp_id = m_fragment_prog.id; - program.modified = false; - } - } - } - m_program.Use();*/ - } - 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 = {}; - - if (m_vertex_prog.bytecode != nullptr) - { - graphicPipelineStateDesc.VS.BytecodeLength = m_vertex_prog.bytecode->GetBufferSize(); - graphicPipelineStateDesc.VS.pShaderBytecode = m_vertex_prog.bytecode->GetBufferPointer(); - } - if (m_fragment_prog.bytecode != nullptr) - { - graphicPipelineStateDesc.PS.BytecodeLength = m_fragment_prog.bytecode->GetBufferSize(); - graphicPipelineStateDesc.PS.pShaderBytecode = m_fragment_prog.bytecode->GetBufferPointer(); - } - - graphicPipelineStateDesc.pRootSignature = rootSignature; - - // Sensible default value - static D3D12_RASTERIZER_DESC CD3D12_RASTERIZER_DESC = - { - D3D12_FILL_MODE_SOLID, - D3D12_CULL_MODE_NONE, - FALSE, - D3D12_DEFAULT_DEPTH_BIAS, - D3D12_DEFAULT_DEPTH_BIAS_CLAMP, - D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, - TRUE, - FALSE, - FALSE, - 0, - D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF, - }; - - static D3D12_DEPTH_STENCIL_DESC CD3D12_DEPTH_STENCIL_DESC = - { - TRUE, - D3D12_DEPTH_WRITE_MASK_ALL, - D3D12_COMPARISON_FUNC_LESS_EQUAL, - FALSE, - D3D12_DEFAULT_STENCIL_READ_MASK, - D3D12_DEFAULT_STENCIL_WRITE_MASK, - }; - - static D3D12_BLEND_DESC CD3D12_BLEND_DESC = - { - FALSE, - FALSE, - { - FALSE,FALSE, - D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, - D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, - D3D12_LOGIC_OP_NOOP, - D3D12_COLOR_WRITE_ENABLE_ALL, - } - }; - - graphicPipelineStateDesc.BlendState = CD3D12_BLEND_DESC; - graphicPipelineStateDesc.DepthStencilState = CD3D12_DEPTH_STENCIL_DESC; - graphicPipelineStateDesc.RasterizerState = CD3D12_RASTERIZER_DESC; - graphicPipelineStateDesc.PrimitiveTopologyType = pipelineProperties.Topology; - - graphicPipelineStateDesc.NumRenderTargets = 1; - graphicPipelineStateDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; - graphicPipelineStateDesc.DSVFormat = DXGI_FORMAT_D16_UNORM; - - graphicPipelineStateDesc.InputLayout.pInputElementDescs = IASet.data(); - graphicPipelineStateDesc.InputLayout.NumElements = (UINT)IASet.size(); - graphicPipelineStateDesc.SampleDesc.Count = 1; - graphicPipelineStateDesc.SampleMask = UINT_MAX; - graphicPipelineStateDesc.NodeMask = 1; - - device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result)); - Add(result, {m_vertex_prog.Id, m_fragment_prog.Id, pipelineProperties }); - - // RSX Debugger - /*if (Ini.GSLogPrograms.GetValue()) - { - RSXDebuggerProgram program; - program.id = m_program.id; - program.vp_id = m_vertex_prog.id; - program.fp_id = m_fragment_prog.id; - program.vp_shader = m_vertex_prog.shader; - program.fp_shader = m_fragment_prog.shader; - m_debug_programs.push_back(program); - }*/ - } - return result; -} - #define TO_STRING(x) #x void Shader::Compile(const std::string &code, SHADER_TYPE st) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h index b3a4d6d8c5..e64ab9fdaa 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h @@ -2,28 +2,37 @@ #if defined (DX12_SUPPORT) #include -#include "Emu/RSX/RSXFragmentProgram.h" -#include "Emu/RSX/RSXVertexProgram.h" #include +#include "../Common/ProgramStateCache.h" +#include "VertexProgramDecompiler.h" +#include "FragmentProgramDecompiler.h" +#include "Utilities/File.h" -enum class SHADER_TYPE -{ - SHADER_TYPE_VERTEX, - SHADER_TYPE_FRAGMENT -}; -struct PipelineProperties +struct D3D12PipelineProperties { D3D12_PRIMITIVE_TOPOLOGY_TYPE Topology; + std::vector IASet; + + bool operator==(const D3D12PipelineProperties &in) const + { + return Topology == in.Topology; + } }; /** Storage for a shader -* Embeds the D3DBlob corresponding to +* Embeds the D3DBlob */ -class Shader +struct Shader { public: + enum class SHADER_TYPE + { + SHADER_TYPE_VERTEX, + SHADER_TYPE_FRAGMENT + }; + Shader() : bytecode(nullptr) {} ~Shader() {} @@ -37,222 +46,127 @@ public: // void Decompile(RSXFragmentProgram& prog) /** Compile the decompiled fragment shader into a format we can use with OpenGL. */ - void Compile(const std::string &code, SHADER_TYPE st); + void Compile(const std::string &code, enum class SHADER_TYPE st); }; - - -namespace ProgramHashUtil +struct D3D12Traits { - // Based on - // https://github.com/AlexAltea/nucleus/blob/master/nucleus/gpu/rsx_pgraph.cpp - union qword - { - u64 dword[2]; - u32 word[4]; - }; + typedef Shader VertexProgramData; + typedef Shader FragmentProgramData; + typedef ID3D12PipelineState PipelineData; + typedef D3D12PipelineProperties PipelineProperties; + typedef std::pair ExtraData; - struct HashVertexProgram + static + void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID) { - size_t operator()(const void *program) const + FragmentDecompiler FS(RSXFP->addr, RSXFP->size, RSXFP->offset); + const std::string &shader = FS.Decompile(); + fragmentProgramData.Compile(shader, Shader::SHADER_TYPE::SHADER_TYPE_FRAGMENT); + + // TODO: This shouldn't use current dir + fs::file("./FragmentProgram.hlsl", o_write | o_create | o_trunc).write(shader.c_str(), shader.size()); + fragmentProgramData.Id = (u32)ID; + } + + static + void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID) + { + VertexDecompiler VS(RSXVP->data); + std::string shaderCode = VS.Decompile(); + vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX); + + // TODO: This shouldn't use current dir + fs::file("./VertexProgram.hlsl", o_write | o_create | o_trunc).write(shaderCode.c_str(), shaderCode.size()); + vertexProgramData.Id = (u32)ID; + } + + static + PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData) + { + ID3D12PipelineState *result; + D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {}; + + if (vertexProgramData.bytecode != nullptr) { - // 64-bit Fowler/Noll/Vo FNV-1a hash code - size_t hash = 0xCBF29CE484222325ULL; - const qword *instbuffer = (const qword*)program; - size_t instIndex = 0; - bool end = false; - return 0; - while (true) + graphicPipelineStateDesc.VS.BytecodeLength = vertexProgramData.bytecode->GetBufferSize(); + graphicPipelineStateDesc.VS.pShaderBytecode = vertexProgramData.bytecode->GetBufferPointer(); + } + if (fragmentProgramData.bytecode != nullptr) + { + graphicPipelineStateDesc.PS.BytecodeLength = fragmentProgramData.bytecode->GetBufferSize(); + graphicPipelineStateDesc.PS.pShaderBytecode = fragmentProgramData.bytecode->GetBufferPointer(); + } + + graphicPipelineStateDesc.pRootSignature = extraData.second; + + // Sensible default value + static D3D12_RASTERIZER_DESC CD3D12_RASTERIZER_DESC = + { + D3D12_FILL_MODE_SOLID, + D3D12_CULL_MODE_NONE, + FALSE, + D3D12_DEFAULT_DEPTH_BIAS, + D3D12_DEFAULT_DEPTH_BIAS_CLAMP, + D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, + TRUE, + FALSE, + FALSE, + 0, + D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF, + }; + + static D3D12_DEPTH_STENCIL_DESC CD3D12_DEPTH_STENCIL_DESC = + { + TRUE, + D3D12_DEPTH_WRITE_MASK_ALL, + D3D12_COMPARISON_FUNC_LESS_EQUAL, + FALSE, + D3D12_DEFAULT_STENCIL_READ_MASK, + D3D12_DEFAULT_STENCIL_WRITE_MASK, + }; + + static D3D12_BLEND_DESC CD3D12_BLEND_DESC = + { + FALSE, + FALSE, { - const qword inst = instbuffer[instIndex]; - bool end = inst.word[0] >> 31; - if (end) - return hash; - hash ^= inst.dword[0]; - hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40); - hash ^= inst.dword[1]; - hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40); - instIndex++; + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, } - return 0; - } - }; + }; + graphicPipelineStateDesc.BlendState = CD3D12_BLEND_DESC; + graphicPipelineStateDesc.DepthStencilState = CD3D12_DEPTH_STENCIL_DESC; + graphicPipelineStateDesc.RasterizerState = CD3D12_RASTERIZER_DESC; + graphicPipelineStateDesc.PrimitiveTopologyType = pipelineProperties.Topology; - struct VertexProgramCompare + graphicPipelineStateDesc.NumRenderTargets = 1; + graphicPipelineStateDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + graphicPipelineStateDesc.DSVFormat = DXGI_FORMAT_D16_UNORM; + + graphicPipelineStateDesc.InputLayout.pInputElementDescs = pipelineProperties.IASet.data(); + graphicPipelineStateDesc.InputLayout.NumElements = (UINT)pipelineProperties.IASet.size(); + graphicPipelineStateDesc.SampleDesc.Count = 1; + graphicPipelineStateDesc.SampleMask = UINT_MAX; + graphicPipelineStateDesc.NodeMask = 1; + + extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&result)); + return result; + } + + static + void DeleteProgram(PipelineData *ptr) { - bool operator()(const void *binary1, const void *binary2) const - { - const qword *instBuffer1 = (const qword*)binary1; - const qword *instBuffer2 = (const qword*)binary2; - size_t instIndex = 0; - return true; - while (true) - { - const qword& inst1 = instBuffer1[instIndex]; - const qword& inst2 = instBuffer2[instIndex]; - bool end = (inst1.word[0] >> 31) && (inst2.word[0] >> 31); - if (end) - return true; - if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1]) - return false; - instIndex++; - } - } - }; - - struct FragmentProgramUtil - { - /** - * returns true if the given source Operand is a constant - */ - static bool isConstant(u32 sourceOperand) - { - return ((sourceOperand >> 8) & 0x3) == 2; - } - - /** - * RSX fragment program constants are inlined inside shader code. - * This function takes an instruction from a fragment program and - * returns an equivalent instruction where inlined constants - * are masked. - * This allows to hash/compare fragment programs even if their - * inlined constants are modified inbetween - */ - static qword fragmentMaskConstant(const qword &initialQword) - { - qword result = initialQword; - if (isConstant(initialQword.word[1])) - result.word[1] = 0; - if (isConstant(initialQword.word[2])) - result.word[2] = 0; - if (isConstant(initialQword.word[3])) - result.word[3] = 0; - return result; - } - }; - - struct HashFragmentProgram - { - size_t operator()(const void *program) const - { - // 64-bit Fowler/Noll/Vo FNV-1a hash code - size_t hash = 0xCBF29CE484222325ULL; - const qword *instbuffer = (const qword*)program; - size_t instIndex = 0; - while (true) - { - const qword& inst = instbuffer[instIndex]; - bool end = (inst.word[0] >> 8) & 0x1; - if (end) - return hash; - const qword& maskedInst = FragmentProgramUtil::fragmentMaskConstant(inst); - hash ^= maskedInst.dword[0]; - hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40); - hash ^= maskedInst.dword[1]; - hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40); - instIndex++; - // Skip constants - if (FragmentProgramUtil::isConstant(inst.word[1]) || - FragmentProgramUtil::isConstant(inst.word[2]) || - FragmentProgramUtil::isConstant(inst.word[3])) - instIndex++; - } - return 0; - } - }; - - struct FragmentProgramCompare - { - bool operator()(const void *binary1, const void *binary2) const - { - const qword *instBuffer1 = (const qword*)binary1; - const qword *instBuffer2 = (const qword*)binary2; - size_t instIndex = 0; - while (true) - { - const qword& inst1 = instBuffer1[instIndex]; - const qword& inst2 = instBuffer2[instIndex]; - bool end = ((inst1.word[0] >> 8) & 0x1) && ((inst2.word[0] >> 8) & 0x1); - if (end) - return true; - - const qword& maskedInst1 = FragmentProgramUtil::fragmentMaskConstant(inst1); - const qword& maskedInst2 = FragmentProgramUtil::fragmentMaskConstant(inst2); - - if (maskedInst1.dword[0] != maskedInst2.dword[0] || maskedInst1.dword[1] != maskedInst2.dword[1]) - return false; - instIndex++; - // Skip constants - if (FragmentProgramUtil::isConstant(inst1.word[1]) || - FragmentProgramUtil::isConstant(inst1.word[2]) || - FragmentProgramUtil::isConstant(inst1.word[3])) - instIndex++; - } - } - }; - -} - -typedef std::unordered_map binary2VS; -typedef std::unordered_map 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()(key.vpIdx); - return hashValue; + ptr->Release(); } }; -struct PSOKeyCompare +class PipelineStateObjectCache : public ProgramStateCache { - 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 - */ -class PipelineStateObjectCache -{ -private: - size_t m_currentShaderId; - binary2VS m_cacheVS; - binary2FS m_cacheFS; - - std::unordered_map m_cachePSO; - - bool SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader); - bool SearchVp(const RSXVertexProgram& rsx_vp, Shader& shader); - ID3D12PipelineState *GetProg(const PSOKey &psoKey) const; - void AddVertexProgram(Shader& vp, RSXVertexProgram& rsx_vp); - void AddFragmentProgram(Shader& fp, RSXFragmentProgram& rsx_fp); - 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 PipelineProperties &pipelineProperties, - const std::vector &IASet - ); }; diff --git a/rpcs3/Emu/RSX/D3D12/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/FragmentProgramDecompiler.cpp index 1cf237caf8..8a88a246e4 100644 --- a/rpcs3/Emu/RSX/D3D12/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/FragmentProgramDecompiler.cpp @@ -69,7 +69,7 @@ void FragmentDecompiler::SetDst(std::string code, bool append_mask) { if (dst.set_cond) { - AddCode("$ifcond " + m_parr.AddParam(PARAM_NONE, typeName[3], "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = " + code + ";"); + AddCode("$ifcond " + m_parr.AddParam(PF_PARAM_NONE, typeName[3], "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = " + code + ";"); } else { @@ -86,7 +86,7 @@ void FragmentDecompiler::SetDst(std::string code, bool append_mask) if (dst.set_cond) { - AddCode(m_parr.AddParam(PARAM_NONE, typeName[3], "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = " + dest + ";"); + AddCode(m_parr.AddParam(PF_PARAM_NONE, typeName[3], "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = " + dest + ";"); } } @@ -114,24 +114,24 @@ std::string FragmentDecompiler::GetMask() std::string FragmentDecompiler::AddReg(u32 index, int fp16) { - return m_parr.AddParam(PARAM_NONE, typeName[3], std::string(fp16 ? "h" : "r") + std::to_string(index), typeName[3] + "(0.0)"); + return m_parr.AddParam(PF_PARAM_NONE, typeName[3], std::string(fp16 ? "h" : "r") + std::to_string(index), typeName[3] + "(0.0)"); } bool FragmentDecompiler::HasReg(u32 index, int fp16) { - return m_parr.HasParam(PARAM_NONE, typeName[3], + return m_parr.HasParam(PF_PARAM_NONE, typeName[3], std::string(fp16 ? "h" : "r") + std::to_string(index)); } std::string FragmentDecompiler::AddCond() { - return m_parr.AddParam(PARAM_NONE, typeName[3], "cc" + std::to_string(src0.cond_reg_index)); + return m_parr.AddParam(PF_PARAM_NONE, typeName[3], "cc" + std::to_string(src0.cond_reg_index)); } std::string FragmentDecompiler::AddConst() { std::string name = std::string("fc") + std::to_string(m_size + 4 * 4); - if (m_parr.HasParam(PARAM_UNIFORM, typeName[3], name)) + if (m_parr.HasParam(PF_PARAM_UNIFORM, typeName[3], name)) { return name; } @@ -143,14 +143,14 @@ std::string FragmentDecompiler::AddConst() u32 y = GetData(data[1]); u32 z = GetData(data[2]); u32 w = GetData(data[3]); - return m_parr.AddParam(PARAM_UNIFORM, typeName[3], name, + return m_parr.AddParam(PF_PARAM_UNIFORM, typeName[3], name, std::string(typeName[3] + "(") + std::to_string((float&)x) + ", " + std::to_string((float&)y) + ", " + std::to_string((float&)z) + ", " + std::to_string((float&)w) + ")"); } std::string FragmentDecompiler::AddTex() { - return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", std::string("tex") + std::to_string(dst.tex_num)); + return m_parr.AddParam(PF_PARAM_UNIFORM, "sampler2D", std::string("tex") + std::to_string(dst.tex_num)); } std::string FragmentDecompiler::Format(const std::string& code) @@ -275,7 +275,7 @@ void FragmentDecompiler::AddCodeCond(const std::string& dst, const std::string& cond = "(" + AddCond() + swizzle + " " + cond + " " + typeName[3] + "(0., 0., 0., 0.))"; - ShaderVar dst_var(dst); + ShaderVariable dst_var(dst); dst_var.symplify(); //const char *c_mask = f; @@ -320,12 +320,12 @@ template std::string FragmentDecompiler::GetSRC(T src) default: if (dst.src_attr_reg_num < sizeof(reg_table) / sizeof(reg_table[0])) { - ret += m_parr.AddParam(PARAM_IN, typeName[3], reg_table[dst.src_attr_reg_num]); + ret += m_parr.AddParam(PF_PARAM_IN, typeName[3], reg_table[dst.src_attr_reg_num]); } else { LOG_ERROR(RSX, "Bad src reg num: %d", fmt::by_value(dst.src_attr_reg_num)); - ret += m_parr.AddParam(PARAM_IN, typeName[3], "unk"); + ret += m_parr.AddParam(PF_PARAM_IN, typeName[3], "unk"); Emu.Pause(); } break; @@ -425,7 +425,7 @@ void FragmentDecompiler::insertOutputs(std::stringstream & OS) for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { - if (m_parr.HasParam(PARAM_NONE, typeName[3], table[i].second)) + if (m_parr.HasParam(PF_PARAM_NONE, typeName[3], table[i].second)) OS << " " << typeName[3] << " " << table[i].first << " : SV_TARGET" << i << ";" << std::endl; } OS << "};" << std::endl; @@ -443,7 +443,7 @@ void FragmentDecompiler::insertConstants(std::stringstream & OS) } OS << "};" << std::endl;*/ - for (ParamType PT : m_parr.params[PARAM_UNIFORM]) + for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM]) { for (ParamItem PI : PT.items) OS << PT.type << " " << PI.name << " = " << PI.value << ";" << std::endl; @@ -454,13 +454,13 @@ void FragmentDecompiler::insertMainStart(std::stringstream & OS) { OS << "PixelOutput main(PixelInput In)" << std::endl; OS << "{" << std::endl; - for (ParamType PT : m_parr.params[PARAM_IN]) + for (ParamType PT : m_parr.params[PF_PARAM_IN]) { for (ParamItem PI : PT.items) OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl; } // Declare output - for (ParamType PT : m_parr.params[PARAM_NONE]) + for (ParamType PT : m_parr.params[PF_PARAM_NONE]) { for (ParamItem PI : PT.items) OS << " " << PT.type << " " << PI.name << " = float4(0., 0., 0., 0.);" << std::endl; @@ -480,7 +480,7 @@ void FragmentDecompiler::insertMainEnd(std::stringstream & OS) OS << " PixelOutput Out;" << std::endl; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { - if (m_parr.HasParam(PARAM_NONE, typeName[3], table[i].second)) + if (m_parr.HasParam(PF_PARAM_NONE, typeName[3], table[i].second)) OS << " Out." << table[i].first << " = " << table[i].second << ";" << std::endl; } OS << " return Out;" << std::endl; diff --git a/rpcs3/Emu/RSX/D3D12/ShaderParam.h b/rpcs3/Emu/RSX/D3D12/ShaderParam.h index 5ef5d3e3d3..c063a9e793 100644 --- a/rpcs3/Emu/RSX/D3D12/ShaderParam.h +++ b/rpcs3/Emu/RSX/D3D12/ShaderParam.h @@ -5,12 +5,12 @@ enum ParamFlag { - PARAM_IN, - PARAM_OUT, - PARAM_UNIFORM, - PARAM_CONST, - PARAM_NONE, - PARAM_COUNT, + PF_PARAM_IN, + PF_PARAM_OUT, + PF_PARAM_UNIFORM, + PF_PARAM_CONST, + PF_PARAM_NONE, + PF_PARAM_COUNT, }; struct ParamItem @@ -51,7 +51,7 @@ struct ParamType struct ParamArray { - std::vector params[PARAM_COUNT]; + std::vector params[PF_PARAM_COUNT]; ParamType* SearchParam(const ParamFlag &flag, const std::string& type) { @@ -105,14 +105,14 @@ struct ParamArray } }; -class ShaderVar +class ShaderVariable { public: std::string name; std::vector swizzles; - ShaderVar() = default; - ShaderVar(const std::string& var) + ShaderVariable() = default; + ShaderVariable(const std::string& var) { auto var_blocks = fmt::split(var, { "." }); @@ -138,7 +138,7 @@ public: return swizzles[swizzles.size() - 1].length(); } - ShaderVar& symplify() + ShaderVariable& symplify() { std::unordered_map swizzle; diff --git a/rpcs3/Emu/RSX/D3D12/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/VertexProgramDecompiler.cpp index 65e1e8b866..0aa100682a 100644 --- a/rpcs3/Emu/RSX/D3D12/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/VertexProgramDecompiler.cpp @@ -52,13 +52,13 @@ std::string VertexDecompiler::GetDST(bool isSca) switch (isSca ? 0x1f : d3.dst) { case 0x1f: - ret += m_parr.AddParam(PARAM_NONE, typeName[3], std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)); + ret += m_parr.AddParam(PF_PARAM_NONE, typeName[3], std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)); break; default: if (d3.dst > 15) LOG_ERROR(RSX, fmt::Format("dst index out of range: %u", d3.dst)); - ret += m_parr.AddParam(PARAM_NONE, typeName[3], std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? typeName[3] + "(0.0f, 0.0f, 0.0f, 1.0f)" : typeName[3] + "(0.0, 0.0, 0.0, 0.0)"); + ret += m_parr.AddParam(PF_PARAM_NONE, typeName[3], std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? typeName[3] + "(0.0f, 0.0f, 0.0f, 1.0f)" : typeName[3] + "(0.0, 0.0, 0.0, 0.0)"); break; } @@ -82,21 +82,21 @@ std::string VertexDecompiler::GetSRC(const u32 n) switch (src[n].reg_type) { case 1: //temp - ret += m_parr.AddParam(PARAM_NONE, typeName[3], "tmp" + std::to_string(src[n].tmp_src)); + ret += m_parr.AddParam(PF_PARAM_NONE, typeName[3], "tmp" + std::to_string(src[n].tmp_src)); break; case 2: //input if (d1.input_src < (sizeof(reg_table) / sizeof(reg_table[0]))) { - ret += m_parr.AddParam(PARAM_IN, typeName[3], reg_table[d1.input_src], d1.input_src); + ret += m_parr.AddParam(PF_PARAM_IN, typeName[3], reg_table[d1.input_src], d1.input_src); } else { LOG_ERROR(RSX, "Bad input src num: %d", fmt::by_value(d1.input_src)); - ret += m_parr.AddParam(PARAM_IN, typeName[3], "in_unk", d1.input_src); + ret += m_parr.AddParam(PF_PARAM_IN, typeName[3], "in_unk", d1.input_src); } break; case 3: //const - m_parr.AddParam(PARAM_UNIFORM, typeName[3], std::string("vc[468]")); + m_parr.AddParam(PF_PARAM_UNIFORM, typeName[3], std::string("vc[468]")); ret += std::string("vc[") + std::to_string(d1.const_src) + (d3.index_const ? " + " + AddAddrReg() : "") + "]"; break; @@ -161,7 +161,7 @@ void VertexDecompiler::SetDST(bool is_sca, std::string value) if (d0.cond_update_enable_0 && d0.cond_update_enable_1) { - dest = m_parr.AddParam(PARAM_NONE, typeName[3], "cc" + std::to_string(d0.cond_reg_sel_1), typeName[3] + "(0.0)") + mask; + dest = m_parr.AddParam(PF_PARAM_NONE, typeName[3], "cc" + std::to_string(d0.cond_reg_sel_1), typeName[3] + "(0.0)") + mask; } else if (d3.dst != 0x1f || (is_sca ? d3.sca_dst_tmp != 0x3f : d0.dst_tmp != 0x3f)) { @@ -197,7 +197,7 @@ std::string VertexDecompiler::GetFunc() std::string VertexDecompiler::GetTex() { - return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", std::string("vtex") + std::to_string(/*?.tex_num*/0)); + return m_parr.AddParam(PF_PARAM_UNIFORM, "sampler2D", std::string("vtex") + std::to_string(/*?.tex_num*/0)); } std::string VertexDecompiler::Format(const std::string& code) @@ -312,7 +312,7 @@ void VertexDecompiler::AddCodeCond(const std::string& dst, const std::string& sr std::string cond = fmt::Format("%s(cc%d%s, vec4(0.0))", cond_string_table[d0.cond], d0.cond_reg_sel_1, swizzle.c_str()); - ShaderVar dst_var(dst); + ShaderVariable dst_var(dst); dst_var.symplify(); //const char *c_mask = f; @@ -340,7 +340,7 @@ std::string VertexDecompiler::AddAddrMask() std::string VertexDecompiler::AddAddrReg() { static const char f[] = { 'x', 'y', 'z', 'w' }; - return m_parr.AddParam(PARAM_NONE, "ivec4", "a" + std::to_string(d0.addr_reg_sel_1), "ivec4(0)") + AddAddrMask(); + return m_parr.AddParam(PF_PARAM_NONE, "ivec4", "a" + std::to_string(d0.addr_reg_sel_1), "ivec4(0)") + AddAddrMask(); } u32 VertexDecompiler::GetAddr() @@ -428,11 +428,11 @@ std::string VertexDecompiler::BuildCode() std::stringstream OS; insertHeader(OS); - insertInputs(OS, m_parr.params[PARAM_IN]); + insertInputs(OS, m_parr.params[PF_PARAM_IN]); OS << std::endl; - insertOutputs(OS, m_parr.params[PARAM_NONE]); + insertOutputs(OS, m_parr.params[PF_PARAM_NONE]); OS << std::endl; - insertConstants(OS, m_parr.params[PARAM_UNIFORM]); + insertConstants(OS, m_parr.params[PF_PARAM_UNIFORM]); OS << std::endl; insertMainStart(OS); @@ -541,11 +541,11 @@ void VertexDecompiler::insertMainStart(std::stringstream & OS) // Declare inside main function for (auto &i : reg_table) { - if (m_parr.HasParam(PARAM_NONE, typeName[3], i.src_reg)) + if (m_parr.HasParam(PF_PARAM_NONE, typeName[3], i.src_reg)) OS << " float4 " << i.src_reg << ";" << std::endl; } - for (const ParamType PT : m_parr.params[PARAM_IN]) + for (const ParamType PT : m_parr.params[PF_PARAM_IN]) { for (const ParamItem &PI : PT.items) OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl; @@ -559,7 +559,7 @@ void VertexDecompiler::insertMainEnd(std::stringstream & OS) // Declare inside main function for (auto &i : reg_table) { - if (m_parr.HasParam(PARAM_NONE, typeName[3], i.src_reg)) + if (m_parr.HasParam(PF_PARAM_NONE, typeName[3], i.src_reg)) OS << " Out." << i.src_reg << " = " << i.src_reg << ";" << std::endl; } // TODO: Find why I need to do this @@ -583,7 +583,7 @@ VertexDecompiler::VertexDecompiler(std::vector& data) : std::string VertexDecompiler::Decompile() { - for (unsigned i = 0; i < PARAM_COUNT; i++) + for (unsigned i = 0; i < PF_PARAM_COUNT; i++) m_parr.params[i].clear(); m_instr_count = 0;