diff --git a/rpcs3/Emu/RSX/CgBinaryProgram.h b/rpcs3/Emu/RSX/CgBinaryProgram.h index c77c1659f1..c92da2a8fc 100644 --- a/rpcs3/Emu/RSX/CgBinaryProgram.h +++ b/rpcs3/Emu/RSX/CgBinaryProgram.h @@ -334,7 +334,9 @@ public: u32 size; u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0); std::vector td; - GLFragmentDecompilerThread(m_glsl_shader, param_array, ptr + vmprog.ucode, size, ctrl, td).Task(); + RSXFragmentProgram prog; + prog.size = 0, prog.addr = ptr + vmprog.ucode, prog.offset = 0, prog.ctrl = ctrl; + GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, size).Task(); vm::close(); } } @@ -383,7 +385,9 @@ public: } TaskVP(); - GLVertexDecompilerThread(m_data, m_glsl_shader, param_array).Task(); + RSXVertexProgram prog; + prog.data = m_data; + GLVertexDecompilerThread(prog, m_glsl_shader, param_array).Task(); } } diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 9d0a09efd9..bbb022ed13 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -4,13 +4,13 @@ #include "FragmentProgramDecompiler.h" -FragmentProgramDecompiler::FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector &texture_dimensions) : - m_addr(addr), +FragmentProgramDecompiler::FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size) : + m_addr(prog.addr), m_size(size), m_const_index(0), m_location(0), - m_ctrl(ctrl), - m_texture_dimensions(texture_dimensions) + m_ctrl(prog.ctrl), + m_texture_dimensions(prog.texture_dimensions) { m_size = 0; } diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h index edaec9ae2d..95d7075bb7 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h @@ -113,6 +113,8 @@ protected: virtual void insertMainEnd(std::stringstream &OS) = 0; public: ParamArray m_parr; - FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector &texture_dimensions); + FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size); + FragmentProgramDecompiler(const FragmentProgramDecompiler&) = delete; + FragmentProgramDecompiler(FragmentProgramDecompiler&&) = delete; std::string Decompile(); }; diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp new file mode 100644 index 0000000000..32b2ebb2d8 --- /dev/null +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -0,0 +1,123 @@ +#include "stdafx.h" +#include "ProgramStateCache.h" + +using namespace program_hash_util; + +size_t vertex_program_hash::operator()(const std::vector &program) const +{ + // 64-bit Fowler/Noll/Vo FNV-1a hash code + size_t hash = 0xCBF29CE484222325ULL; + const qword *instbuffer = (const qword*)program.data(); + size_t instIndex = 0; + bool end = false; + for (unsigned i = 0; i < program.size() / 4; i++) + { + const qword inst = instbuffer[instIndex]; + 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++; + } + return hash; +} + +bool vertex_program_compare::operator()(const std::vector &binary1, const std::vector &binary2) const +{ + if (binary1.size() != binary2.size()) return false; + const qword *instBuffer1 = (const qword*)binary1.data(); + const qword *instBuffer2 = (const qword*)binary2.data(); + size_t instIndex = 0; + for (unsigned i = 0; i < binary1.size() / 4; i++) + { + const qword& inst1 = instBuffer1[instIndex]; + const qword& inst2 = instBuffer2[instIndex]; + if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1]) + return false; + instIndex++; + } + return true; +} + + +bool fragment_program_utils::is_constant(u32 sourceOperand) +{ + return ((sourceOperand >> 8) & 0x3) == 2; +} + +size_t fragment_program_utils::get_fragment_program_ucode_size(void *ptr) +{ + const qword *instBuffer = (const qword*)ptr; + size_t instIndex = 0; + while (true) + { + const qword& inst = instBuffer[instIndex]; + bool isSRC0Constant = is_constant(inst.word[1]); + bool isSRC1Constant = is_constant(inst.word[2]); + bool isSRC2Constant = is_constant(inst.word[3]); + 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; + } +} + +size_t fragment_program_hash::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]; + 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++; + // Skip constants + if (fragment_program_utils::is_constant(inst.word[1]) || + fragment_program_utils::is_constant(inst.word[2]) || + fragment_program_utils::is_constant(inst.word[3])) + instIndex++; + + bool end = (inst.word[0] >> 8) & 0x1; + if (end) + return hash; + } + return 0; +} + +bool fragment_program_compare::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]; + + if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1]) + return false; + instIndex++; + // Skip constants + if (fragment_program_utils::is_constant(inst1.word[1]) || + fragment_program_utils::is_constant(inst1.word[2]) || + fragment_program_utils::is_constant(inst1.word[3])) + instIndex++; + + bool end = ((inst1.word[0] >> 8) & 0x1) && ((inst2.word[0] >> 8) & 0x1); + if (end) + return true; + } +} diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.h b/rpcs3/Emu/RSX/Common/ProgramStateCache.h index 509264aaa2..aba88af224 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.h +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.h @@ -2,6 +2,7 @@ #include "Emu/RSX/RSXFragmentProgram.h" #include "Emu/RSX/RSXVertexProgram.h" +#include "Emu/Memory/vm.h" enum class SHADER_TYPE @@ -10,7 +11,7 @@ enum class SHADER_TYPE SHADER_TYPE_FRAGMENT }; -namespace ProgramHashUtil +namespace program_hash_util { // Based on // https://github.com/AlexAltea/nucleus/blob/master/nucleus/gpu/rsx_pgraph.cpp @@ -20,142 +21,34 @@ namespace ProgramHashUtil u32 word[4]; }; - struct HashVertexProgram + struct vertex_program_hash { - size_t operator()(const std::vector &program) const - { - // 64-bit Fowler/Noll/Vo FNV-1a hash code - size_t hash = 0xCBF29CE484222325ULL; - const qword *instbuffer = (const qword*)program.data(); - size_t instIndex = 0; - bool end = false; - for (unsigned i = 0; i < program.size() / 4; i++) - { - const qword inst = instbuffer[instIndex]; - 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++; - } - return hash; - } + size_t operator()(const std::vector &program) const; }; - - struct VertexProgramCompare + struct vertex_program_compare { - bool operator()(const std::vector &binary1, const std::vector &binary2) const - { - if (binary1.size() != binary2.size()) return false; - const qword *instBuffer1 = (const qword*)binary1.data(); - const qword *instBuffer2 = (const qword*)binary2.data(); - size_t instIndex = 0; - for (unsigned i = 0; i < binary1.size() / 4; i++) - { - const qword& inst1 = instBuffer1[instIndex]; - const qword& inst2 = instBuffer2[instIndex]; - if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1]) - return false; - instIndex++; - } - return true; - } + bool operator()(const std::vector &binary1, const std::vector &binary2) const; }; - struct FragmentProgramUtil + struct fragment_program_utils { /** * returns true if the given source Operand is a constant */ - static bool isConstant(u32 sourceOperand) - { - return ((sourceOperand >> 8) & 0x3) == 2; - } + static bool is_constant(u32 sourceOperand); - static - size_t getFPBinarySize(void *ptr) - { - const qword *instBuffer = (const qword*)ptr; - size_t instIndex = 0; - while (true) - { - const qword& inst = instBuffer[instIndex]; - bool isSRC0Constant = isConstant(inst.word[1]); - bool isSRC1Constant = isConstant(inst.word[2]); - bool isSRC2Constant = isConstant(inst.word[3]); - 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; - } - } + static size_t get_fragment_program_ucode_size(void *ptr); }; - struct HashFragmentProgram + struct fragment_program_hash { - 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]; - 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++; - // Skip constants - if (FragmentProgramUtil::isConstant(inst.word[1]) || - FragmentProgramUtil::isConstant(inst.word[2]) || - FragmentProgramUtil::isConstant(inst.word[3])) - instIndex++; - - bool end = (inst.word[0] >> 8) & 0x1; - if (end) - return hash; - } - return 0; - } + size_t operator()(const void *program) const; }; - struct FragmentProgramCompare + struct fragment_program_compare { - 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]; - - if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1]) - return false; - instIndex++; - // Skip constants - if (FragmentProgramUtil::isConstant(inst1.word[1]) || - FragmentProgramUtil::isConstant(inst1.word[2]) || - FragmentProgramUtil::isConstant(inst1.word[3])) - instIndex++; - - bool end = ((inst1.word[0] >> 8) & 0x1) && ((inst2.word[0] >> 8) & 0x1); - if (end) - return true; - } - } + bool operator()(const void *binary1, const void *binary2) const; }; } @@ -170,193 +63,170 @@ namespace ProgramHashUtil * - a typedef PipelineProperties to a type that encapsulate various state info relevant to program compilation (alpha test, primitive type,...) * - a typedef ExtraData type that will be passed to the buildProgram function. * It should also contains the following function member : -* - static void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID); -* - static void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID); -* - static PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData); -* - void DeleteProgram(PipelineData *ptr); +* - static void recompile_fragment_program(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID); +* - static void recompile_vertex_program(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID); +* - static PipelineData build_program(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData); */ -template -class ProgramStateCache +template +class program_state_cache { -private: - typedef std::unordered_map, typename BackendTraits::VertexProgramData, ProgramHashUtil::HashVertexProgram, ProgramHashUtil::VertexProgramCompare> binary2VS; - typedef std::unordered_map binary2FS; - binary2VS m_cacheVS; - binary2FS m_cacheFS; + using pipeline_storage_type = typename backend_traits::pipeline_storage_type; + using pipeline_properties = typename backend_traits::pipeline_properties; + using vertex_program_type = typename backend_traits::vertex_program_type; + using fragment_program_type = typename backend_traits::fragment_program_type; - size_t m_currentShaderId; - std::vector dummyFragmentConstantCache; + using binary_to_vertex_program = std::unordered_map, vertex_program_type, program_hash_util::vertex_program_hash, program_hash_util::vertex_program_compare> ; + using binary_to_fragment_program = std::unordered_map; - struct PSOKey + + struct pipeline_key { - u32 vpIdx; - u32 fpIdx; - typename BackendTraits::PipelineProperties properties; + u32 vertex_program_id; + u32 fragment_program_id; + pipeline_properties properties; }; - struct PSOKeyHash + struct pipeline_key_hash { - size_t operator()(const PSOKey &key) const + size_t operator()(const pipeline_key &key) const { size_t hashValue = 0; - hashValue ^= std::hash()(key.vpIdx); - hashValue ^= std::hash()(key.fpIdx); - hashValue ^= std::hash()(key.properties); + hashValue ^= std::hash()(key.vertex_program_id); + hashValue ^= std::hash()(key.fragment_program_id); + hashValue ^= std::hash()(key.properties); return hashValue; } }; - struct PSOKeyCompare + struct pipeline_key_compare { - size_t operator()(const PSOKey &key1, const PSOKey &key2) const + bool operator()(const pipeline_key &key1, const pipeline_key &key2) const { - return (key1.vpIdx == key2.vpIdx) && (key1.fpIdx == key2.fpIdx) && (key1.properties == key2.properties); + return (key1.vertex_program_id == key2.vertex_program_id) && (key1.fragment_program_id == key2.fragment_program_id) && (key1.properties == key2.properties); } }; - std::unordered_map m_cachePSO; +private: + size_t m_next_id = 0; + binary_to_vertex_program m_vertex_shader_cache; + binary_to_fragment_program m_fragment_shader_cache; + std::unordered_map m_storage; - typename BackendTraits::FragmentProgramData& SearchFp(RSXFragmentProgram* rsx_fp, bool& found) + /// bool here to inform that the program was preexisting. + std::tuple search_vertex_program(const RSXVertexProgram& rsx_vp) { - typename binary2FS::iterator It = m_cacheFS.find(vm::base(rsx_fp->addr)); - if (It != m_cacheFS.end()) + const auto& I = m_vertex_shader_cache.find(rsx_vp.data); + if (I != m_vertex_shader_cache.end()) { - found = true; - return It->second; + return std::forward_as_tuple(I->second, true); } - found = false; - LOG_WARNING(RSX, "FP not found in buffer!"); - size_t actualFPSize = ProgramHashUtil::FragmentProgramUtil::getFPBinarySize(vm::base(rsx_fp->addr)); - void *fpShadowCopy = malloc(actualFPSize); - std::memcpy(fpShadowCopy, vm::base(rsx_fp->addr), actualFPSize); - typename BackendTraits::FragmentProgramData &newShader = m_cacheFS[fpShadowCopy]; - BackendTraits::RecompileFragmentProgram(rsx_fp, newShader, m_currentShaderId++); + LOG_NOTICE(RSX, "VP not found in buffer!"); + vertex_program_type& new_shader = m_vertex_shader_cache[rsx_vp.data]; + backend_traits::recompile_vertex_program(rsx_vp, new_shader, m_next_id++); - return newShader; + return std::forward_as_tuple(new_shader, false); } - typename BackendTraits::VertexProgramData& SearchVp(RSXVertexProgram* rsx_vp, bool &found) + /// bool here to inform that the program was preexisting. + std::tuple search_fragment_program(const RSXFragmentProgram& rsx_fp) { - typename binary2VS::iterator It = m_cacheVS.find(rsx_vp->data); - if (It != m_cacheVS.end()) + const auto& I = m_fragment_shader_cache.find(vm::base(rsx_fp.addr)); + if (I != m_fragment_shader_cache.end()) { - found = true; - return It->second; + return std::forward_as_tuple(I->second, true); } - found = false; - LOG_WARNING(RSX, "VP not found in buffer!"); - typename BackendTraits::VertexProgramData& newShader = m_cacheVS[rsx_vp->data]; - BackendTraits::RecompileVertexProgram(rsx_vp, newShader, m_currentShaderId++); + LOG_NOTICE(RSX, "FP not found in buffer!"); + size_t fragment_program_size = program_hash_util::fragment_program_utils::get_fragment_program_ucode_size(vm::base(rsx_fp.addr)); + gsl::not_null fragment_program_ucode_copy = malloc(fragment_program_size); + std::memcpy(fragment_program_ucode_copy, vm::base(rsx_fp.addr), fragment_program_size); + fragment_program_type &new_shader = m_fragment_shader_cache[fragment_program_ucode_copy]; + backend_traits::recompile_fragment_program(rsx_fp, new_shader, m_next_id++); - return newShader; - } - - typename BackendTraits::PipelineData *GetProg(const PSOKey &psoKey) const - { - typename std::unordered_map::const_iterator It = m_cachePSO.find(psoKey); - if (It == m_cachePSO.end()) - return nullptr; - return It->second; - } - - void Add(typename BackendTraits::PipelineData *prog, const PSOKey& PSOKey) - { - m_cachePSO.insert(std::make_pair(PSOKey, prog)); + return std::forward_as_tuple(new_shader, false); } public: - ProgramStateCache() : m_currentShaderId(0) {} - ~ProgramStateCache() + program_state_cache() = default; + ~program_state_cache() = default; + + const vertex_program_type& get_transform_program(const RSXVertexProgram& rsx_vp) const { - clear(); + auto I = m_vertex_shader_cache.find(rsx_vp.data); + if (I == m_vertex_shader_cache.end()) + return I->second; + throw new EXCEPTION("Trying to get unknow transform program"); } - const typename BackendTraits::VertexProgramData* get_transform_program(const RSXVertexProgram& rsx_vp) const + const fragment_program_type& get_shader_program(const RSXFragmentProgram& rsx_fp) const { - typename binary2VS::const_iterator It = m_cacheVS.find(rsx_vp.data); - if (It == m_cacheVS.end()) - return nullptr; - return &It->second; + auto I = m_fragment_shader_cache.find(vm::base(rsx_fp.addr)); + if (I != m_fragment_shader_cache.end()) + return I->second; + throw new EXCEPTION("Trying to get unknow shader program"); } - const typename BackendTraits::FragmentProgramData* get_shader_program(const RSXFragmentProgram& rsx_fp) const - { - typename binary2FS::const_iterator It = m_cacheFS.find(vm::base(rsx_fp.addr)); - if (It == m_cacheFS.end()) - return nullptr; - return &It->second; - } - - void clear() - { - for (auto pair : m_cachePSO) - BackendTraits::DeleteProgram(pair.second); - m_cachePSO.clear(); - - for (auto pair : m_cacheFS) - free(pair.first); - - m_cacheFS.clear(); - } - - typename BackendTraits::PipelineData *getGraphicPipelineState( - RSXVertexProgram *vertexShader, - RSXFragmentProgram *fragmentShader, - const typename BackendTraits::PipelineProperties &pipelineProperties, - const typename BackendTraits::ExtraData& extraData + template + pipeline_storage_type& getGraphicPipelineState( + const RSXVertexProgram& vertexShader, + const RSXFragmentProgram& fragmentShader, + const pipeline_properties& pipelineProperties, + Args&& ...args ) { - typename BackendTraits::PipelineData *result = nullptr; - bool fpFound, vpFound; - typename BackendTraits::VertexProgramData &vertexProg = SearchVp(vertexShader, vpFound); - typename BackendTraits::FragmentProgramData &fragmentProg = SearchFp(fragmentShader, fpFound); + // TODO : use tie and implicit variable declaration syntax with c++17 + const auto &vp_search = search_vertex_program(vertexShader); + const auto &fp_search = search_fragment_program(fragmentShader); + const vertex_program_type &vertex_program = std::get<0>(vp_search); + const fragment_program_type &fragment_program = std::get<0>(fp_search); + bool already_existing_fragment_program = std::get<1>(fp_search); + bool already_existing_vertex_program = std::get<1>(vp_search); - if (fpFound && vpFound) + pipeline_key key = { vertex_program.id, fragment_program.id, pipelineProperties }; + + if (already_existing_fragment_program && already_existing_vertex_program) { - result = GetProg({ vertexProg.id, fragmentProg.id, pipelineProperties }); + const auto I = m_storage.find(key); + if (I != m_storage.end()) + return I->second; } - if (result != nullptr) - return result; - else - { - LOG_WARNING(RSX, "Add program :"); - LOG_WARNING(RSX, "*** vp id = %d", vertexProg.id); - LOG_WARNING(RSX, "*** fp id = %d", fragmentProg.id); + LOG_NOTICE(RSX, "Add program :"); + LOG_NOTICE(RSX, "*** vp id = %d", vertex_program.id); + LOG_NOTICE(RSX, "*** fp id = %d", fragment_program.id); - result = BackendTraits::BuildProgram(vertexProg, fragmentProg, pipelineProperties, extraData); - Add(result, { vertexProg.id, fragmentProg.id, pipelineProperties }); - } - return result; + m_storage[key] = backend_traits::build_pipeline(vertex_program, fragment_program, pipelineProperties, std::forward(args)...); + return m_storage[key]; } - size_t get_fragment_constants_buffer_size(const RSXFragmentProgram *fragmentShader) const + size_t get_fragment_constants_buffer_size(const RSXFragmentProgram &fragmentShader) const { - typename binary2FS::const_iterator It = m_cacheFS.find(vm::base(fragmentShader->addr)); - if (It != m_cacheFS.end()) - return It->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float); + const auto I = m_fragment_shader_cache.find(vm::base(fragmentShader.addr)); + if (I != m_fragment_shader_cache.end()) + return I->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float); LOG_ERROR(RSX, "Can't retrieve constant offset cache"); return 0; } - void fill_fragment_constans_buffer(void *buffer, const RSXFragmentProgram *fragment_program) const + void fill_fragment_constans_buffer(gsl::span dst_buffer, const RSXFragmentProgram &fragment_program) const { - typename binary2FS::const_iterator It = m_cacheFS.find(vm::base(fragment_program->addr)); - if (It == m_cacheFS.end()) + const auto I = m_fragment_shader_cache.find(vm::base(fragment_program.addr)); + if (I == m_fragment_shader_cache.end()) return; __m128i mask = _mm_set_epi8(0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1); + Expects(dst_buffer.size_bytes() >= gsl::narrow(I->second.FragmentConstantOffsetCache.size()) * 16); + size_t offset = 0; - for (size_t offset_in_fragment_program : It->second.FragmentConstantOffsetCache) + for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache) { - void *data = vm::base(fragment_program->addr + (u32)offset_in_fragment_program); + void *data = vm::base(fragment_program.addr + (u32)offset_in_fragment_program); const __m128i &vector = _mm_loadu_si128((__m128i*)data); const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask); - _mm_stream_si128((__m128i*)((char*)buffer + offset), shuffled_vector); - offset += 4 * sizeof(u32); + _mm_stream_si128((__m128i*)dst_buffer.subspan(offset, 4).data(), shuffled_vector); + offset += sizeof(f32); } } }; diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp index 237d946cff..d48240513a 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp @@ -435,8 +435,8 @@ std::string VertexProgramDecompiler::BuildCode() return OS.str(); } -VertexProgramDecompiler::VertexProgramDecompiler(std::vector& data) : - m_data(data) +VertexProgramDecompiler::VertexProgramDecompiler(const RSXVertexProgram& prog) : + m_data(prog.data) { m_funcs.emplace_back(); m_funcs[0].offset = 0; diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h index ab4aac0d01..e01dc5f2ba 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h @@ -57,7 +57,7 @@ struct VertexProgramDecompiler //wxString main; - std::vector& m_data; + const std::vector& m_data; ParamArray m_parr; std::string GetMask(bool is_sca); @@ -124,6 +124,6 @@ protected: */ virtual void insertMainEnd(std::stringstream &OS) = 0; public: - VertexProgramDecompiler(std::vector& data); + VertexProgramDecompiler(const RSXVertexProgram& prog); std::string Decompile(); }; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 24a6e00af0..fed8ad14e9 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -206,7 +206,7 @@ void D3D12GSRender::upload_and_bind_vertex_shader_constants(size_t descriptor_in void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_index) { // Get constant from fragment program - size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(&fragment_program); + size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(fragment_program); // Multiple of 256 never 0 buffer_size = (buffer_size + 255) & ~255; @@ -216,7 +216,8 @@ void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_ size_t offset = 0; void *mapped_buffer; CHECK_HRESULT(m_constants_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), &mapped_buffer)); - m_pso_cache.fill_fragment_constans_buffer((char*)mapped_buffer + heap_offset, &fragment_program); + float *buffer = (float*)((char*)mapped_buffer + heap_offset); + m_pso_cache.fill_fragment_constans_buffer({ buffer, gsl::narrow(buffer_size) }, fragment_program); m_constants_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp index 43ae0dbf6b..b14e9046b1 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp @@ -6,8 +6,8 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" -D3D12FragmentDecompiler::D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector &texture_dimensions) : - FragmentProgramDecompiler(addr, size, ctrl, texture_dimensions) +D3D12FragmentDecompiler::D3D12FragmentDecompiler(const RSXFragmentProgram &prog, u32& size) : + FragmentProgramDecompiler(prog, size) { } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.h b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.h index 29882f8126..e4a58f1f09 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.h @@ -20,5 +20,5 @@ protected: virtual void insertMainStart(std::stringstream &OS) override; virtual void insertMainEnd(std::stringstream &OS) override; public: - D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector &texture_dimensions); + D3D12FragmentDecompiler(const RSXFragmentProgram &prog, u32& size); }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index f6d50187d1..4bfe538f92 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -87,7 +87,7 @@ D3D12DLLManagement::~D3D12DLLManagement() } D3D12GSRender::D3D12GSRender() - : GSRender(frame_type::DX12), m_d3d12_lib(), m_current_pso(nullptr) + : GSRender(frame_type::DX12), m_d3d12_lib(), m_current_pso({}) { m_previous_address_a = 0; m_previous_address_b = 0; @@ -277,7 +277,7 @@ void D3D12GSRender::end() std::chrono::time_point program_load_end = std::chrono::system_clock::now(); m_timers.m_program_load_duration += std::chrono::duration_cast(program_load_end - program_load_start).count(); - get_current_resource_storage().command_list->SetGraphicsRootSignature(m_root_signatures[std::get<2>(*m_current_pso)].Get()); + get_current_resource_storage().command_list->SetGraphicsRootSignature(m_root_signatures[std::get<2>(m_current_pso)].Get()); get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]); std::chrono::time_point constants_duration_start = std::chrono::system_clock::now(); @@ -291,12 +291,12 @@ void D3D12GSRender::end() std::chrono::time_point constants_duration_end = std::chrono::system_clock::now(); m_timers.m_constants_duration += std::chrono::duration_cast(constants_duration_end - constants_duration_start).count(); - get_current_resource_storage().command_list->SetPipelineState(std::get<0>(*m_current_pso)); + get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get()); std::chrono::time_point texture_duration_start = std::chrono::system_clock::now(); - if (std::get<2>(*m_current_pso) > 0) + if (std::get<2>(m_current_pso) > 0) { - upload_and_bind_textures(get_current_resource_storage().command_list.Get(), currentDescriptorIndex + 3, std::get<2>(*m_current_pso) > 0); + upload_and_bind_textures(get_current_resource_storage().command_list.Get(), currentDescriptorIndex + 3, std::get<2>(m_current_pso) > 0); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0, @@ -308,8 +308,8 @@ void D3D12GSRender::end() .Offset((INT)get_current_resource_storage().current_sampler_index, g_descriptor_stride_samplers) ); - get_current_resource_storage().current_sampler_index += std::get<2>(*m_current_pso); - get_current_resource_storage().descriptors_heap_index += std::get<2>(*m_current_pso) + 3; + get_current_resource_storage().current_sampler_index += std::get<2>(m_current_pso); + get_current_resource_storage().descriptors_heap_index += std::get<2>(m_current_pso) + 3; } else { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 143ba42243..dbaa4ab0bd 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -67,7 +67,7 @@ private: RSXVertexProgram vertex_program; RSXFragmentProgram fragment_program; PipelineStateObjectCache m_pso_cache; - std::tuple, size_t> *m_current_pso; + std::tuple, std::vector, size_t> m_current_pso; struct { @@ -146,7 +146,7 @@ private: void init_d2d_structures(); void release_d2d_structures(); - bool load_program(); + void load_program(); void set_rtt_and_ds(ID3D12GraphicsCommandList *command_list); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index 477b05acf5..e3c8f1a714 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -36,7 +36,7 @@ void Shader::Compile(const std::string &code, SHADER_TYPE st) } } -bool D3D12GSRender::load_program() +void D3D12GSRender::load_program() { u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START]; vertex_program.data.reserve((512 - transform_program_start) * 4); @@ -256,12 +256,12 @@ bool D3D12GSRender::load_program() prop.CutValue = ((rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4) == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32) ? D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF : D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF; - m_current_pso = m_pso_cache.getGraphicPipelineState(&vertex_program, &fragment_program, prop, std::make_pair(m_device.Get(), m_root_signatures)); - return m_current_pso != nullptr; + m_current_pso = m_pso_cache.getGraphicPipelineState(vertex_program, fragment_program, prop, m_device.Get(), m_root_signatures); + return; } std::pair D3D12GSRender::get_programs() const { - return std::make_pair(m_pso_cache.get_transform_program(vertex_program)->content, m_pso_cache.get_shader_program(fragment_program)->content); + return std::make_pair(m_pso_cache.get_transform_program(vertex_program).content, m_pso_cache.get_shader_program(fragment_program).content); } #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h index d4c4a8bb0c..ef4ba8db27 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h @@ -85,8 +85,9 @@ public: SHADER_TYPE_FRAGMENT }; - Shader() : bytecode(nullptr) {} - ~Shader() {} + Shader() = default; + ~Shader() = default; + Shader(const Shader &) = delete; u32 id; ComPtr bytecode; @@ -137,16 +138,16 @@ std::vector completes_IA_desc(const std::vector, size_t> PipelineData; - typedef D3D12PipelineProperties PipelineProperties; - typedef std::pair *> ExtraData; + using vertex_program_type = Shader; + using fragment_program_type = Shader; + using pipeline_storage_type = std::tuple, std::vector, size_t>; + using pipeline_properties = D3D12PipelineProperties; static - void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID) + void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t ID) { - D3D12FragmentDecompiler FS(RSXFP->addr, RSXFP->size, RSXFP->ctrl, RSXFP->texture_dimensions); + u32 size; + D3D12FragmentDecompiler FS(RSXFP, size); const std::string &shader = FS.Decompile(); fragmentProgramData.Compile(shader, Shader::SHADER_TYPE::SHADER_TYPE_FRAGMENT); fragmentProgramData.m_textureCount = 0; @@ -170,9 +171,9 @@ struct D3D12Traits } static - void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID) + void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t ID) { - D3D12VertexProgramDecompiler VS(RSXVP->data); + D3D12VertexProgramDecompiler VS(RSXVP); std::string shaderCode = VS.Decompile(); vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX); vertexProgramData.vertex_shader_inputs = VS.input_slots; @@ -181,24 +182,24 @@ struct D3D12Traits } static - PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData) + pipeline_storage_type build_pipeline( + const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties &pipelineProperties, + ID3D12Device *device, gsl::span, 17> root_signatures) { - - std::tuple, size_t> *result = new std::tuple, size_t>(); + std::tuple, size_t> result = {}; D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {}; if (vertexProgramData.bytecode == nullptr) - return nullptr; + throw new EXCEPTION("Vertex program compilation failure"); graphicPipelineStateDesc.VS.BytecodeLength = vertexProgramData.bytecode->GetBufferSize(); graphicPipelineStateDesc.VS.pShaderBytecode = vertexProgramData.bytecode->GetBufferPointer(); if (fragmentProgramData.bytecode == nullptr) - return nullptr; + throw new EXCEPTION("fragment program compilation failure"); graphicPipelineStateDesc.PS.BytecodeLength = fragmentProgramData.bytecode->GetBufferSize(); graphicPipelineStateDesc.PS.pShaderBytecode = fragmentProgramData.bytecode->GetBufferPointer(); - graphicPipelineStateDesc.pRootSignature = extraData.second[fragmentProgramData.m_textureCount].Get(); - std::get<2>(*result) = fragmentProgramData.m_textureCount; + graphicPipelineStateDesc.pRootSignature = root_signatures[fragmentProgramData.m_textureCount].Get(); graphicPipelineStateDesc.BlendState = pipelineProperties.Blend; graphicPipelineStateDesc.DepthStencilState = pipelineProperties.DepthStencil; @@ -220,22 +221,15 @@ struct D3D12Traits graphicPipelineStateDesc.IBStripCutValue = pipelineProperties.CutValue; - CHECK_HRESULT(extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&std::get<0>(*result)))); - std::get<1>(*result) = vertexProgramData.vertex_shader_inputs; + ComPtr pso; + CHECK_HRESULT(device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(pso.GetAddressOf()))); std::wstring name = L"PSO_" + std::to_wstring(vertexProgramData.id) + L"_" + std::to_wstring(fragmentProgramData.id); - std::get<0>(*result)->SetName(name.c_str()); - return result; - } - - static - void DeleteProgram(PipelineData *ptr) - { - std::get<0>(*ptr)->Release(); - delete ptr; + pso->SetName(name.c_str()); + return std::make_tuple(pso, vertexProgramData.vertex_shader_inputs, fragmentProgramData.m_textureCount); } }; -class PipelineStateObjectCache : public ProgramStateCache +class PipelineStateObjectCache : public program_state_cache { }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp index fe5a908594..7d663411d6 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp @@ -181,8 +181,8 @@ void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS) OS << "}" << std::endl; } -D3D12VertexProgramDecompiler::D3D12VertexProgramDecompiler(std::vector& data) : - VertexProgramDecompiler(data) +D3D12VertexProgramDecompiler::D3D12VertexProgramDecompiler(const RSXVertexProgram &prog) : + VertexProgramDecompiler(prog) { } #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h index bdc1655cd4..fd5a55a7a8 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.h @@ -20,5 +20,5 @@ protected: virtual void insertMainEnd(std::stringstream &OS); public: std::vector input_slots; - D3D12VertexProgramDecompiler(std::vector& data); + D3D12VertexProgramDecompiler(const RSXVertexProgram &prog); }; diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 82814d861d..7d343de314 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -172,9 +172,10 @@ GLFragmentProgram::~GLFragmentProgram() // } //} -void GLFragmentProgram::Decompile(RSXFragmentProgram& prog, const std::vector &td) +void GLFragmentProgram::Decompile(const RSXFragmentProgram& prog) { - GLFragmentDecompilerThread decompiler(shader, parr, prog.addr, prog.size, prog.ctrl, td); + u32 size; + GLFragmentDecompilerThread decompiler(shader, parr, prog, size); decompiler.Task(); for (const ParamType& PT : decompiler.m_parr.params[PF_PARAM_UNIFORM]) { diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h index 4a1f07c03d..f7364e46cc 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h @@ -9,8 +9,8 @@ struct GLFragmentDecompilerThread : public FragmentProgramDecompiler std::string& m_shader; ParamArray& m_parrDummy; public: - GLFragmentDecompilerThread(std::string& shader, ParamArray& parr, u32 addr, u32& size, u32 ctrl, const std::vector &texture_dimensions) - : FragmentProgramDecompiler(addr, size, ctrl, texture_dimensions) + GLFragmentDecompilerThread(std::string& shader, ParamArray& parr, const RSXFragmentProgram &prog, u32& size) + : FragmentProgramDecompiler(prog, size) , m_shader(shader) , m_parrDummy(parr) { @@ -51,7 +51,7 @@ public: * @param prog RSXShaderProgram specifying the location and size of the shader in memory * @param td texture dimensions of input textures */ - void Decompile(RSXFragmentProgram& prog, const std::vector &td); + void Decompile(const RSXFragmentProgram& prog); /** Compile the decompiled fragment shader into a format we can use with OpenGL. */ void Compile(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 22f025d0bd..9ab40ae66d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -576,8 +576,6 @@ void GLGSRender::on_exit() if (m_fragment_constants_buffer) m_fragment_constants_buffer.remove(); - - m_prog_buffer.clear(); } void nv4097_clear_surface(u32 arg, GLGSRender* renderer) @@ -698,7 +696,7 @@ bool GLGSRender::load_program() fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d); } - __glcheck m_program = m_prog_buffer.getGraphicPipelineState(&vertex_program, &fragment_program, nullptr, nullptr); + __glcheck m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr); __glcheck m_program->use(); #else @@ -750,10 +748,10 @@ bool GLGSRender::load_program() glUnmapBuffer(GL_UNIFORM_BUFFER); glBindBuffer(GL_UNIFORM_BUFFER, m_fragment_constants_buffer.id()); - size_t buffer_size = m_prog_buffer.get_fragment_constants_buffer_size(&fragment_program); + size_t buffer_size = m_prog_buffer.get_fragment_constants_buffer_size(fragment_program); glBufferData(GL_UNIFORM_BUFFER, buffer_size, nullptr, GL_STATIC_DRAW); buffer = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); - m_prog_buffer.fill_fragment_constans_buffer(buffer, &fragment_program); + m_prog_buffer.fill_fragment_constans_buffer({ static_cast(buffer), gsl::narrow(buffer_size) }, fragment_program); glUnmapBuffer(GL_UNIFORM_BUFFER); return true; diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h index 0bb8313a9e..823064a176 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h @@ -5,16 +5,15 @@ struct GLTraits { - typedef GLVertexProgram VertexProgramData; - typedef GLFragmentProgram FragmentProgramData; - typedef gl::glsl::program PipelineData; - typedef void* PipelineProperties; - typedef void* ExtraData; + using vertex_program_type = GLVertexProgram; + using fragment_program_type = GLFragmentProgram; + using pipeline_storage_type = gl::glsl::program; + using pipeline_properties = void*; static - void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID) + void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t ID) { - fragmentProgramData.Decompile(*RSXFP, RSXFP->texture_dimensions); + fragmentProgramData.Decompile(RSXFP); fragmentProgramData.Compile(); //checkForGlError("m_fragment_prog.Compile"); @@ -22,9 +21,9 @@ struct GLTraits } static - void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID) + void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t ID) { - vertexProgramData.Decompile(*RSXVP); + vertexProgramData.Decompile(RSXVP); vertexProgramData.Compile(); //checkForGlError("m_vertex_prog.Compile"); @@ -32,10 +31,10 @@ struct GLTraits } static - PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData) + pipeline_storage_type build_pipeline(const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties &pipelineProperties) { - PipelineData *result = new PipelineData(); - __glcheck result->create() + pipeline_storage_type result; + __glcheck result.create() .attach(gl::glsl::shader_view(vertexProgramData.id)) .attach(gl::glsl::shader_view(fragmentProgramData.id)) .bind_fragment_data_location("ocol0", 0) @@ -43,9 +42,9 @@ struct GLTraits .bind_fragment_data_location("ocol2", 2) .bind_fragment_data_location("ocol3", 3) .make(); - __glcheck result->use(); + __glcheck result.use(); - LOG_NOTICE(RSX, "*** prog id = %d", result->id()); + LOG_NOTICE(RSX, "*** prog id = %d", result.id()); LOG_NOTICE(RSX, "*** vp id = %d", vertexProgramData.id); LOG_NOTICE(RSX, "*** fp id = %d", fragmentProgramData.id); @@ -54,14 +53,8 @@ struct GLTraits return result; } - - static - void DeleteProgram(PipelineData *ptr) - { - ptr->remove(); - } }; -class GLProgramBuffer : public ProgramStateCache +class GLProgramBuffer : public program_state_cache { }; diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 415411db6d..5b2fcaefaa 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -166,9 +166,9 @@ GLVertexProgram::~GLVertexProgram() // } //} -void GLVertexProgram::Decompile(RSXVertexProgram& prog) +void GLVertexProgram::Decompile(const RSXVertexProgram& prog) { - GLVertexDecompilerThread decompiler(prog.data, shader, parr); + GLVertexDecompilerThread decompiler(prog, shader, parr); decompiler.Task(); } diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.h b/rpcs3/Emu/RSX/GL/GLVertexProgram.h index 44e4a5e097..fc116b7470 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.h +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.h @@ -20,8 +20,8 @@ protected: virtual void insertMainStart(std::stringstream &OS) override; virtual void insertMainEnd(std::stringstream &OS) override; public: - GLVertexDecompilerThread(std::vector& data, std::string& shader, ParamArray& parr) - : VertexProgramDecompiler(data) + GLVertexDecompilerThread(const RSXVertexProgram &prog, std::string& shader, ParamArray& parr) + : VertexProgramDecompiler(prog) , m_shader(shader) { } @@ -39,7 +39,7 @@ public: u32 id = 0; std::string shader; - void Decompile(RSXVertexProgram& prog); + void Decompile(const RSXVertexProgram& prog); void Compile(); private: diff --git a/rpcs3/Emu/RSX/GL/gl_helpers.h b/rpcs3/Emu/RSX/GL/gl_helpers.h index a57ae47f92..c2914eea4a 100644 --- a/rpcs3/Emu/RSX/GL/gl_helpers.h +++ b/rpcs3/Emu/RSX/GL/gl_helpers.h @@ -2148,7 +2148,7 @@ namespace gl } program() = default; - program(program&) = delete; + program(const program&) = delete; program(program&& program_) { swap(program_); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index b7481ccaf9..92f54a1b3b 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -124,6 +124,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 659e72fb71..8ea7f0719f 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -933,6 +933,9 @@ Source Files + + Emu\GPU\RSX\Common +