diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index 5c6052bcf3..f51d1a3d30 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -2,6 +2,7 @@ #if defined (DX12_SUPPORT) #include "D3D12PipelineState.h" +#include "D3D12ProgramDisassembler.h" #include "Emu/Memory/vm.h" #include "Utilities/Log.h" #include @@ -10,7 +11,7 @@ #pragma comment (lib, "d3dcompiler.lib") -std::unordered_map > CachedShader; + struct GLBufferInfo { @@ -25,8 +26,6 @@ struct GLBufferInfo Microsoft::WRL::ComPtr vp_bytecode; }; -// Copied from GL implementation - enum class SHADER_TYPE { SHADER_TYPE_VERTEX, @@ -42,26 +41,14 @@ public: Shader() : bytecode(nullptr) {} ~Shader() {} -// GLParamArray parr; - u32 id; - std::string shader; Microsoft::WRL::ComPtr bytecode; + std::vector RSXBinary; /** * Decompile a fragment shader located in the PS3's Memory. This function operates synchronously. * @param prog RSXShaderProgram specifying the location and size of the shader in memory */ -// void Decompile(RSXFragmentProgram& prog); - - /** - * Asynchronously decompile a fragment shader located in the PS3's Memory. - * When this function is called you must call Wait() before GetShaderText() will return valid data. - * @param prog RSXShaderProgram specifying the location and size of the shader in memory - */ -// void DecompileAsync(RSXFragmentProgram& prog); - - /** Wait for the decompiler task to complete decompilation. */ -// void Wait(); +// void Decompile(RSXFragmentProgram& prog) /** Compile the decompiled fragment shader into a format we can use with OpenGL. */ void Compile(SHADER_TYPE st) @@ -92,58 +79,171 @@ public: break; } } - -private: - /** Threaded fragment shader decompiler responsible for decompiling this program */ -// GLFragmentDecompilerThread* m_decompiler_thread; - - /** Deletes the shader and any stored information */ -// void Delete(); }; -// Could be improved with an (un)ordered map ? +// Based on +// https://github.com/AlexAltea/nucleus/blob/master/nucleus/gpu/rsx_pgraph.cpp +union qword +{ + u64 dword[2]; + u32 word[4]; +}; + +size_t getVPBinarySize(void *ptr) +{ + const qword *instBuffer = (const qword*)ptr; + size_t instIndex = 0; + while (true) + { + const qword& inst = instBuffer[instIndex]; + bool end = inst.word[0] & 0x1; + if (end) + return (instIndex + 1) * 4; + instIndex++; + } +} + +size_t getFPBinarySize(void *ptr) +{ + const qword *instBuffer = (const qword*)ptr; + size_t instIndex = 0; + while (true) + { + const qword& inst = instBuffer[instIndex]; + bool end = (inst.word[0] >> 8) & 0x1; + if (end) + return (instIndex + 1) * 4; + instIndex++; + } +} + +struct HashVertexProgram +{ + 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; + bool end = false; + return 0; + while (true) + { + 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++; + } + return 0; + } +}; + +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; + 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 0; + } +}; + +struct VertexProgramCompare +{ + 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] >> 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 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; + if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1]) + return false; + instIndex++; + } + } +}; + +typedef std::unordered_map binary2VS; +typedef std::unordered_map binary2FS; +static int tmp = 0; class ProgramBuffer { - std::vector m_buf; public: - int SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader) + binary2VS cacheVS; + binary2FS cacheFS; + + bool SearchFp(const RSXFragmentProgram& rsx_fp, Shader& shader) { - int n = m_buf.size(); - for (int i = 0; i < m_buf.size(); ++i) + binary2FS::const_iterator It = cacheFS.find(vm::get_ptr(rsx_fp.addr)); + if (It != cacheFS.end()) { - if (memcmp(&m_buf[i].fp_data[0], vm::get_ptr(rsx_fp.addr), m_buf[i].fp_data.size()) != 0) continue; - - shader.id = m_buf[i].fp_id; - shader.shader = m_buf[i].fp_shader.c_str(); - shader.bytecode = m_buf[i].fp_bytecode; - - return i; + shader = It->second; + return true; } - - return -1; + return false; } - int SearchVp(const RSXVertexProgram& rsx_vp, Shader& shader) + bool SearchVp(const RSXVertexProgram& rsx_vp, Shader& shader) { - for (u32 i = 0; i < m_buf.size(); ++i) + binary2VS::const_iterator It = cacheVS.find((void*)rsx_vp.data.data()); + if (It != cacheVS.end()) { - if (m_buf[i].vp_data.size() != rsx_vp.data.size()) continue; - if (memcmp(m_buf[i].vp_data.data(), rsx_vp.data.data(), rsx_vp.data.size() * 4) != 0) continue; - - shader.id = m_buf[i].vp_id; - shader.shader = m_buf[i].vp_shader.c_str(); - shader.bytecode = m_buf[i].vp_bytecode; - - return i; + shader = It->second; + return true; } - - return -1; + return false; } - ID3D12PipelineState *GetProg(u32 fp, u32 vp) const +/* ID3D12PipelineState *GetProg(u32 fp, u32 vp) const { if (fp == vp) - { + {*/ /* LOG_NOTICE(RSX, "Get program (%d):", fp); LOG_NOTICE(RSX, "*** prog id = %d", m_buf[fp].prog_id); @@ -153,15 +253,15 @@ public: 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; +/* return m_buf[fp].prog_id; } for (u32 i = 0; i(rsx_fp.addr)); + void *fpShadowCopy = malloc(actualFPSize); + memcpy(fpShadowCopy, vm::get_ptr(rsx_fp.addr), actualFPSize); + cacheFS.insert(std::make_pair(fpShadowCopy, fp)); + } void Add(ID3D12PipelineState *prog, Shader& fp, RSXFragmentProgram& rsx_fp, Shader& vp, RSXVertexProgram& rsx_vp) { - GLBufferInfo new_buf = {}; - - LOG_NOTICE(RSX, "Add program (%d):", m_buf.size()); +/* LOG_NOTICE(RSX, "Add program (%d):", m_buf.size()); LOG_NOTICE(RSX, "*** prog id = %x", prog); LOG_NOTICE(RSX, "*** vp id = %d", vp.id); LOG_NOTICE(RSX, "*** fp id = %d", fp.id); @@ -191,23 +308,7 @@ public: 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()); - - - new_buf.prog_id = prog; - new_buf.vp_id = vp.id; - new_buf.fp_id = fp.id; - new_buf.fp_bytecode = fp.bytecode; - - new_buf.fp_data.insert(new_buf.fp_data.end(), vm::get_ptr(rsx_fp.addr), vm::get_ptr(rsx_fp.addr + rsx_fp.size)); - new_buf.vp_data = rsx_vp.data; - new_buf.vp_bytecode = vp.bytecode; - - new_buf.vp_shader = vp.shader; - new_buf.fp_shader = fp.shader; - - m_buf.resize(m_buf.size() + 1); - m_buf.push_back(new_buf); + LOG_NOTICE(RSX, "*** fp shader = \n%s", fp.shader.c_str());*/ } }; @@ -216,30 +317,32 @@ static ProgramBuffer g_cachedProgram; D3D12PipelineState::D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *vertexShader, RSXFragmentProgram *fragmentShader) { Shader m_vertex_prog, m_fragment_prog; - int m_fp_buf_num = g_cachedProgram.SearchFp(*fragmentShader, m_fragment_prog); - int m_vp_buf_num = g_cachedProgram.SearchVp(*vertexShader, m_vertex_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); - if (m_fp_buf_num == -1) + if (!m_fp_buf_num) { LOG_WARNING(RSX, "FP not found in buffer!"); -// m_fragment_prog.Decompile(*fragmentShader); +// Decompile(*fragmentShader); m_fragment_prog.Compile(SHADER_TYPE::SHADER_TYPE_FRAGMENT); + g_cachedProgram.AddFragmentProgram(m_fragment_prog, *fragmentShader); // TODO: This shouldn't use current dir -// fs::file("./FragmentProgram.txt", o_write | o_create | o_trunc).write(m_fragment_prog.shader.c_str(), m_fragment_prog.shader.size()); + //fs::file("./FragmentProgram.txt", o_write | o_create | o_trunc).write(m_fragment_prog.shader.c_str(), m_fragment_prog.shader.size()); } - if (m_vp_buf_num == -1) + if (!m_vp_buf_num) { LOG_WARNING(RSX, "VP not found in buffer!"); // m_vertex_prog.Decompile(*vertexShader); m_vertex_prog.Compile(SHADER_TYPE::SHADER_TYPE_VERTEX); + g_cachedProgram.AddVertexProgram(m_vertex_prog, *vertexShader); // TODO: This shouldn't use current dir // 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 != -1 && m_vp_buf_num != -1) { // m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num); } @@ -280,11 +383,11 @@ D3D12PipelineState::D3D12PipelineState(ID3D12Device *device, RSXVertexProgram *v { 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.PS.BytecodeLength = m_fragment_prog.bytecode->GetBufferSize(); graphicPipelineStateDesc.PS.pShaderBytecode = m_fragment_prog.bytecode->GetBufferPointer(); - device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&m_pipelineStateObject)); + device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&m_pipelineStateObject));*/ g_cachedProgram.Add(m_pipelineStateObject, m_fragment_prog, *fragmentShader, m_vertex_prog, *vertexShader); /*m_program.Create(m_vertex_prog.id, m_fragment_prog.id); checkForGlError("m_program.Create"); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.cpp new file mode 100644 index 0000000000..af3451cbfc --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.cpp @@ -0,0 +1,268 @@ +#include "stdafx.h" +#if defined (DX12_SUPPORT) +#include "D3D12ProgramDisassembler.h" +#include "Emu/Memory/vm.h" +#include "Utilities/Log.h" + +static u32 GetData(const u32 d) { return d << 16 | d >> 16; } + +void Decompile(RSXFragmentProgram& prog) +{ + auto data = vm::ptr::make(prog.addr); + size_t m_size = 0; + size_t m_location = 0; + size_t m_loop_count = 0; + size_t m_code_level = 1; + + enum + { + FORCE_NONE, + FORCE_SCT, + FORCE_SCB, + }; + + int forced_unit = FORCE_NONE; + + OPDEST operandDST; + + while (true) + { + operandDST.HEX = GetData(data[0]); +/* for (auto finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size); + finded != m_end_offsets.end(); + finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size)) + { + m_end_offsets.erase(finded); + m_code_level--; + AddCode("}"); + m_loop_count--; + }*/ + +/* for (auto finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size); + finded != m_else_offsets.end(); + finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size)) + { + m_else_offsets.erase(finded); + m_code_level--; + AddCode("}"); + AddCode("else"); + AddCode("{"); + m_code_level++; + } + + dst.HEX = GetData(data[0]); + src0.HEX = GetData(data[1]); + src1.HEX = GetData(data[2]); + src2.HEX = GetData(data[3]); + + m_offset = 4 * sizeof(u32); + + const u32 opcode = dst.opcode | (src1.opcode_is_branch << 6); + + auto SCT = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); break; + case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); break; + case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1))"); break; + case RSX_FP_OPCODE_DP2: SetDst("vec4(dot($0.xy, $1.xy))"); break; + case RSX_FP_OPCODE_DP3: SetDst("vec4(dot($0.xyz, $1.xyz))"); break; + case RSX_FP_OPCODE_DP4: SetDst("vec4(dot($0, $1))"); break; + case RSX_FP_OPCODE_DP2A: SetDst("vec4($0.x * $1.x + $0.y * $1.y + $2.x)"); break; + case RSX_FP_OPCODE_MAD: SetDst("($0 * $1 + $2)"); break; + case RSX_FP_OPCODE_MAX: SetDst("max($0, $1)"); break; + case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); break; + case RSX_FP_OPCODE_MOV: SetDst("$0"); break; + case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); break; + case RSX_FP_OPCODE_RCP: SetDst("1 / $0"); break; + case RSX_FP_OPCODE_RSQ: SetDst("inversesqrt(abs($0))"); break; + case RSX_FP_OPCODE_SEQ: SetDst("vec4(equal($0, $1))"); break; + case RSX_FP_OPCODE_SFL: SetDst("vec4(0.0)"); break; + case RSX_FP_OPCODE_SGE: SetDst("vec4(greaterThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SGT: SetDst("vec4(greaterThan($0, $1))"); break; + case RSX_FP_OPCODE_SLE: SetDst("vec4(lessThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SLT: SetDst("vec4(lessThan($0, $1))"); break; + case RSX_FP_OPCODE_SNE: SetDst("vec4(notEqual($0, $1))"); break; + case RSX_FP_OPCODE_STR: SetDst("vec4(1.0)"); break; + + default: + return false; + } + + return true; + }; + + auto SCB = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); break; + case RSX_FP_OPCODE_COS: SetDst("cos($0)"); break; + case RSX_FP_OPCODE_DP2: SetDst("vec4(dot($0.xy, $1.xy))"); break; + case RSX_FP_OPCODE_DP3: SetDst("vec4(dot($0.xyz, $1.xyz))"); break; + case RSX_FP_OPCODE_DP4: SetDst("vec4(dot($0, $1))"); break; + case RSX_FP_OPCODE_DP2A: SetDst("vec4($0.x * $1.x + $0.y * $1.y + $2.x)"); break; + case RSX_FP_OPCODE_DST: SetDst("vec4(distance($0, $1))"); break; + case RSX_FP_OPCODE_REFL: LOG_ERROR(RSX, "Unimplemented SCB instruction: REFL"); break; // TODO: Is this in the right category? + case RSX_FP_OPCODE_EX2: SetDst("exp2($0)"); break; + case RSX_FP_OPCODE_FLR: SetDst("floor($0)"); break; + case RSX_FP_OPCODE_FRC: SetDst("fract($0)"); break; + case RSX_FP_OPCODE_LIT: SetDst("vec4(1.0, $0.x, ($0.x > 0.0 ? exp($0.w * log2($0.y)) : 0.0), 1.0)"); break; + case RSX_FP_OPCODE_LIF: SetDst("vec4(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); break; + case RSX_FP_OPCODE_LRP: LOG_ERROR(RSX, "Unimplemented SCB instruction: LRP"); break; // TODO: Is this in the right category? + case RSX_FP_OPCODE_LG2: SetDst("log2($0)"); break; + case RSX_FP_OPCODE_MAD: SetDst("($0 * $1 + $2)"); break; + case RSX_FP_OPCODE_MAX: SetDst("max($0, $1)"); break; + case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); break; + case RSX_FP_OPCODE_MOV: SetDst("$0"); break; + case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); break; + case RSX_FP_OPCODE_PK2: SetDst("packSnorm2x16($0)"); break; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478)) + case RSX_FP_OPCODE_PK4: SetDst("packSnorm4x8($0)"); break; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478)) + case RSX_FP_OPCODE_PK16: LOG_ERROR(RSX, "Unimplemented SCB instruction: PK16"); break; + case RSX_FP_OPCODE_PKB: LOG_ERROR(RSX, "Unimplemented SCB instruction: PKB"); break; + case RSX_FP_OPCODE_PKG: LOG_ERROR(RSX, "Unimplemented SCB instruction: PKG"); break; + case RSX_FP_OPCODE_SEQ: SetDst("vec4(equal($0, $1))"); break; + case RSX_FP_OPCODE_SFL: SetDst("vec4(0.0)"); break; + case RSX_FP_OPCODE_SGE: SetDst("vec4(greaterThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SGT: SetDst("vec4(greaterThan($0, $1))"); break; + case RSX_FP_OPCODE_SIN: SetDst("sin($0)"); break; + case RSX_FP_OPCODE_SLE: SetDst("vec4(lessThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SLT: SetDst("vec4(lessThan($0, $1))"); break; + case RSX_FP_OPCODE_SNE: SetDst("vec4(notEqual($0, $1))"); break; + case RSX_FP_OPCODE_STR: SetDst("vec4(1.0)"); break; + + default: + return false; + } + + return true; + }; + + auto TEX_SRB = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_DDX: SetDst("dFdx($0)"); break; + case RSX_FP_OPCODE_DDY: SetDst("dFdy($0)"); break; + case RSX_FP_OPCODE_NRM: SetDst("normalize($0)"); break; + case RSX_FP_OPCODE_BEM: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: BEM"); break; + case RSX_FP_OPCODE_TEX: SetDst("texture($t, $0.xy)"); break; + case RSX_FP_OPCODE_TEXBEM: SetDst("texture($t, $0.xy, $1.x)"); break; + case RSX_FP_OPCODE_TXP: SetDst("textureProj($t, $0.xyz, $1.x)"); break; //TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478) and The Simpsons Arcade Game (NPUB30563)) + case RSX_FP_OPCODE_TXPBEM: SetDst("textureProj($t, $0.xyz, $1.x)"); break; + case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); break; + case RSX_FP_OPCODE_TXB: SetDst("texture($t, $0.xy, $1.x)"); break; + case RSX_FP_OPCODE_TXL: SetDst("textureLod($t, $0.xy, $1.x)"); break; + case RSX_FP_OPCODE_UP2: SetDst("unpackSnorm2x16($0)"); break; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478)) + case RSX_FP_OPCODE_UP4: SetDst("unpackSnorm4x8($0)"); break; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478)) + case RSX_FP_OPCODE_UP16: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UP16"); break; + case RSX_FP_OPCODE_UPB: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UPB"); break; + case RSX_FP_OPCODE_UPG: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UPG"); break; + + default: + return false; + } + + return true; + }; + + auto SIP = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_BRK: SetDst("break"); break; + case RSX_FP_OPCODE_CAL: LOG_ERROR(RSX, "Unimplemented SIP instruction: CAL"); break; + case RSX_FP_OPCODE_FENCT: forced_unit = FORCE_SCT; break; + case RSX_FP_OPCODE_FENCB: forced_unit = FORCE_SCB; break; + case RSX_FP_OPCODE_IFE: + AddCode("if($cond)"); + m_else_offsets.push_back(src1.else_offset << 2); + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + break; + case RSX_FP_OPCODE_LOOP: + if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) + { + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //LOOP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset)); + } + else + { + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment)); + m_loop_count++; + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + } + break; + case RSX_FP_OPCODE_REP: + if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) + { + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //REP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset)); + } + else + { + AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment)); + m_loop_count++; + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + } + break; + case RSX_FP_OPCODE_RET: SetDst("return"); break; + + default: + return false; + } + + return true; + }; + + switch (opcode) + { + case RSX_FP_OPCODE_NOP: break; + case RSX_FP_OPCODE_KIL: SetDst("discard", false); break; + + default: + if (forced_unit == FORCE_NONE) + { + if (SIP()) break; + if (SCT()) break; + if (TEX_SRB()) break; + if (SCB()) break; + } + else if (forced_unit == FORCE_SCT) + { + forced_unit = FORCE_NONE; + if (SCT()) break; + } + else if (forced_unit == FORCE_SCB) + { + forced_unit = FORCE_NONE; + if (SCB()) break; + } + + LOG_ERROR(RSX, "Unknown/illegal instruction: 0x%x (forced unit %d)", opcode, forced_unit); + break; + } + + m_size += m_offset;*/ + + if (operandDST.end) break; + +// assert(m_offset % sizeof(u32) == 0); + data += 4 / sizeof(u32); + } + + // flush m_code_level + m_code_level = 1; +/* m_shader = BuildCode(); + main.clear(); + m_parr.params.clear();*/ +} +#endif \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.h b/rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.h new file mode 100644 index 0000000000..011cef292e --- /dev/null +++ b/rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.h @@ -0,0 +1,6 @@ +#pragma once +#if defined (DX12_SUPPORT) +#include "Emu/RSX/RSXFragmentProgram.h" + +void Decompile(RSXFragmentProgram& prog); +#endif \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/DefaultPixelShader.hlsl b/rpcs3/Emu/RSX/D3D12/DefaultPixelShader.hlsl deleted file mode 100644 index 68075ef0c2..0000000000 --- a/rpcs3/Emu/RSX/D3D12/DefaultPixelShader.hlsl +++ /dev/null @@ -1,4 +0,0 @@ -float4 main() : SV_TARGET -{ - return float4(1.0f, 1.0f, 1.0f, 1.0f); -} \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 125c782d6f..4d595b4823 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -42,8 +42,6 @@ - - @@ -502,7 +500,6 @@ - @@ -630,9 +627,6 @@ - - - {C4A10229-4712-4BD2-B63E-50D93C67A038} emucore diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 2e2b882156..ca6c9fc43b 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -971,12 +971,6 @@ Emu\GPU\RSX\D3D12 - - Emu\GPU\RSX\D3D12 - - - Emu\GPU\RSX\D3D12 - @@ -1846,13 +1840,5 @@ Emu\GPU\RSX\D3D12 - - Emu\GPU\RSX\D3D12 - - - - - Emu\GPU\RSX\D3D12 - \ No newline at end of file