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