mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-12 13:13:43 +00:00
d3d12: Fragment Program caching works
But not VP...
This commit is contained in:
parent
3f24da47a0
commit
c29616b341
@ -2,6 +2,7 @@
|
||||
#if defined (DX12_SUPPORT)
|
||||
|
||||
#include "D3D12PipelineState.h"
|
||||
#include "D3D12ProgramDisassembler.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include <wrl/client.h>
|
||||
@ -10,7 +11,7 @@
|
||||
|
||||
#pragma comment (lib, "d3dcompiler.lib")
|
||||
|
||||
std::unordered_map<std::string, Microsoft::WRL::ComPtr<ID3DBlob> > CachedShader;
|
||||
|
||||
|
||||
struct GLBufferInfo
|
||||
{
|
||||
@ -25,8 +26,6 @@ struct GLBufferInfo
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> 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<ID3DBlob> bytecode;
|
||||
std::vector<u8> 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<void *, Shader, HashVertexProgram, VertexProgramCompare> binary2VS;
|
||||
typedef std::unordered_map<void *, Shader, HashFragmentProgram, FragmentProgramCompare> binary2FS;
|
||||
static int tmp = 0;
|
||||
class ProgramBuffer
|
||||
{
|
||||
std::vector<GLBufferInfo> 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<void>(rsx_fp.addr));
|
||||
if (It != cacheFS.end())
|
||||
{
|
||||
if (memcmp(&m_buf[i].fp_data[0], vm::get_ptr<void>(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<m_buf.size(); ++i)
|
||||
{
|
||||
if (i == fp || i == vp) continue;
|
||||
if (i == fp || i == vp) continue;*/
|
||||
|
||||
// if (CmpVP(vp, i) && CmpFP(fp, i))
|
||||
{
|
||||
// {
|
||||
/*
|
||||
LOG_NOTICE(RSX, "Get program (%d):", i);
|
||||
LOG_NOTICE(RSX, "*** prog id = %d", m_buf[i].prog_id);
|
||||
@ -171,19 +271,36 @@ public:
|
||||
LOG_NOTICE(RSX, "*** vp shader = \n%s", m_buf[i].vp_shader.wx_str());
|
||||
LOG_NOTICE(RSX, "*** fp shader = \n%s", m_buf[i].fp_shader.wx_str());
|
||||
*/
|
||||
return m_buf[i].prog_id;
|
||||
/* return m_buf[i].prog_id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
void AddVertexProgram(const Shader& vp, RSXVertexProgram& rsx_vp)
|
||||
{
|
||||
size_t actualVPSize = getVPBinarySize(rsx_vp.data.data());
|
||||
void *fpShadowCopy = malloc(actualVPSize);
|
||||
memcpy(fpShadowCopy, rsx_vp.data.data(), actualVPSize);
|
||||
int* tmpint = (int*)fpShadowCopy;
|
||||
if (tmp++)
|
||||
LOG_WARNING(RSX, "vp:%x %x %x %x\n", tmpint[0], tmpint[1], tmpint[2], tmpint[3]);
|
||||
|
||||
cacheVS.insert(std::make_pair(fpShadowCopy, vp));
|
||||
}
|
||||
|
||||
void AddFragmentProgram(const Shader& fp, RSXFragmentProgram& rsx_fp)
|
||||
{
|
||||
size_t actualFPSize = getFPBinarySize(vm::get_ptr<u8>(rsx_fp.addr));
|
||||
void *fpShadowCopy = malloc(actualFPSize);
|
||||
memcpy(fpShadowCopy, vm::get_ptr<u8>(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<u8>(rsx_fp.addr), vm::get_ptr<u8>(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");
|
||||
|
268
rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.cpp
Normal file
268
rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.cpp
Normal file
@ -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<u32>::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
|
6
rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.h
Normal file
6
rpcs3/Emu/RSX/D3D12/D3D12ProgramDisassembler.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#if defined (DX12_SUPPORT)
|
||||
#include "Emu/RSX/RSXFragmentProgram.h"
|
||||
|
||||
void Decompile(RSXFragmentProgram& prog);
|
||||
#endif
|
@ -1,4 +0,0 @@
|
||||
float4 main() : SV_TARGET
|
||||
{
|
||||
return float4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
@ -42,8 +42,6 @@
|
||||
<ClCompile Include="Emu\RSX\Common\ShaderParam.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\VertexProgramDecompiler.cpp" />
|
||||
<ClCompile Include="Emu\RSX\D3D12\D3D12GSRender.cpp" />
|
||||
<ClCompile Include="Emu\RSX\D3D12\D3D12PipelineState.cpp" />
|
||||
<ClCompile Include="Emu\RSX\D3D12\D3D12RenderTargetSets.cpp" />
|
||||
<ClCompile Include="Emu\RSX\GL\GLCommonDecompiler.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sys_dbg.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\sys_fs.cpp" />
|
||||
@ -502,7 +500,6 @@
|
||||
<ClInclude Include="Emu\RSX\Common\ShaderParam.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\VertexProgramDecompiler.h" />
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12GSRender.h" />
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12PipelineState.h" />
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12RenderTargetSets.h" />
|
||||
<ClInclude Include="Emu\RSX\GCM.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\GLBuffers.h" />
|
||||
@ -630,9 +627,6 @@
|
||||
<ClInclude Include="Emu\Cell\PPULLVMRecompiler.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="Emu\RSX\D3D12\DefaultPixelShader.hlsl" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C4A10229-4712-4BD2-B63E-50D93C67A038}</ProjectGuid>
|
||||
<RootNamespace>emucore</RootNamespace>
|
||||
|
@ -971,12 +971,6 @@
|
||||
<ClCompile Include="Emu\RSX\D3D12\D3D12GSRender.cpp">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\D3D12\D3D12PipelineState.cpp">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\D3D12\D3D12RenderTargetSets.cpp">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -1846,13 +1840,5 @@
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12RenderTargetSets.h">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12PipelineState.h">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="Emu\RSX\D3D12\DefaultPixelShader.hlsl">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user