mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added shader disassembler
This commit is contained in:
parent
a0d7cffc07
commit
2248a07113
@ -12,6 +12,7 @@
|
||||
#include <D3dDdi/DeviceFuncs.h>
|
||||
#include <D3dDdi/Resource.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <D3dDdi/ShaderAssembler.h>
|
||||
#include <DDraw/ScopedThreadLock.h>
|
||||
|
||||
namespace
|
||||
@ -247,6 +248,13 @@ namespace D3dDdi
|
||||
return m_origVtable.pfnColorFill(m_device, data);
|
||||
}
|
||||
|
||||
HRESULT Device::pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code)
|
||||
{
|
||||
LOG_DEBUG << "Pixel shader bytecode: " << Compat::hexDump(code, data->CodeSize);
|
||||
LOG_DEBUG << ShaderAssembler(code, data->CodeSize).disassemble();
|
||||
return m_origVtable.pfnCreatePixelShader(m_device, data, code);
|
||||
}
|
||||
|
||||
HRESULT Device::pfnCreateResource(D3DDDIARG_CREATERESOURCE* data)
|
||||
{
|
||||
D3DDDIARG_CREATERESOURCE2 data2 = {};
|
||||
@ -277,6 +285,13 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Device::pfnCreateVertexShaderFunc(D3DDDIARG_CREATEVERTEXSHADERFUNC* data, const UINT* code)
|
||||
{
|
||||
LOG_DEBUG << "Vertex shader bytecode: " << Compat::hexDump(code, data->Size);
|
||||
LOG_DEBUG << ShaderAssembler(code, data->Size).disassemble();
|
||||
return m_origVtable.pfnCreateVertexShaderFunc(m_device, data, code);
|
||||
}
|
||||
|
||||
HRESULT Device::pfnDepthFill(const D3DDDIARG_DEPTHFILL* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
|
@ -33,8 +33,10 @@ namespace D3dDdi
|
||||
HRESULT pfnBlt(const D3DDDIARG_BLT* data);
|
||||
HRESULT pfnClear(const D3DDDIARG_CLEAR* data, UINT numRect, const RECT* rect);
|
||||
HRESULT pfnColorFill(const D3DDDIARG_COLORFILL* data);
|
||||
HRESULT pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code);
|
||||
HRESULT pfnCreateResource(D3DDDIARG_CREATERESOURCE* data);
|
||||
HRESULT pfnCreateResource2(D3DDDIARG_CREATERESOURCE2* data);
|
||||
HRESULT pfnCreateVertexShaderFunc(D3DDDIARG_CREATEVERTEXSHADERFUNC* data, const UINT* code);
|
||||
HRESULT pfnDepthFill(const D3DDDIARG_DEPTHFILL* data);
|
||||
HRESULT pfnDestroyDevice();
|
||||
HRESULT pfnDestroyResource(HANDLE resource);
|
||||
|
@ -54,6 +54,8 @@ namespace
|
||||
SET_DEVICE_FUNC(pfnColorFill);
|
||||
SET_DEVICE_FUNC(pfnCreateResource);
|
||||
SET_DEVICE_FUNC(pfnCreateResource2);
|
||||
SET_DEVICE_FUNC(pfnCreatePixelShader);
|
||||
SET_DEVICE_FUNC(pfnCreateVertexShaderFunc);
|
||||
SET_DEVICE_FUNC(pfnDepthFill);
|
||||
SET_DEVICE_FUNC(pfnDestroyDevice);
|
||||
SET_DEVICE_FUNC(pfnDestroyResource);
|
||||
|
563
DDrawCompat/D3dDdi/ShaderAssembler.cpp
Normal file
563
DDrawCompat/D3dDdi/ShaderAssembler.cpp
Normal file
@ -0,0 +1,563 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include <D3dDdi/ShaderAssembler.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const UINT BEGIN_BLOCK = 1;
|
||||
const UINT END_BLOCK = 2;
|
||||
|
||||
typedef std::array<const char*, 7> Controls;
|
||||
|
||||
const Controls CMP_CONTROLS = { nullptr, "gt", "eq", "ge", "lt", "ne", "le" };
|
||||
const Controls TEXLD_CONTROLS = { "", "p", "b" };
|
||||
|
||||
struct CommentToken
|
||||
{
|
||||
UINT32 opcode : 16;
|
||||
UINT32 tokenCount : 15;
|
||||
UINT32 : 1;
|
||||
};
|
||||
|
||||
struct Instruction
|
||||
{
|
||||
const char* name;
|
||||
UINT dstCount = 0;
|
||||
UINT srcCount = 0;
|
||||
UINT extraCount = 0;
|
||||
UINT indent = 0;
|
||||
const Controls* controls = nullptr;
|
||||
};
|
||||
|
||||
struct InstructionToken
|
||||
{
|
||||
UINT32 opcode : 16;
|
||||
UINT32 control : 8;
|
||||
UINT32 tokenCount : 4;
|
||||
UINT32 isPredicated : 1;
|
||||
UINT32 : 3;
|
||||
};
|
||||
|
||||
struct VersionToken
|
||||
{
|
||||
UINT32 minor : 8;
|
||||
UINT32 major : 8;
|
||||
UINT32 type : 16;
|
||||
};
|
||||
|
||||
std::map<UINT16, Instruction> g_instructionMap = {
|
||||
{ D3DSIO_NOP, { "nop" } },
|
||||
{ D3DSIO_MOV, { "mov", 1, 1 } },
|
||||
{ D3DSIO_ADD, { "add", 1, 2 } },
|
||||
{ D3DSIO_SUB, { "sub", 1, 2 } },
|
||||
{ D3DSIO_MAD, { "mad", 1, 3 } },
|
||||
{ D3DSIO_MUL, { "mul", 1, 2 } },
|
||||
{ D3DSIO_RCP, { "rcp", 1, 1 } },
|
||||
{ D3DSIO_RSQ, { "rsq", 1, 1 } },
|
||||
{ D3DSIO_DP3, { "dp3", 1, 2 } },
|
||||
{ D3DSIO_DP4, { "dp4", 1, 2 } },
|
||||
{ D3DSIO_MIN, { "min", 1, 2 } },
|
||||
{ D3DSIO_MAX, { "max", 1, 2 } },
|
||||
{ D3DSIO_SLT, { "slt", 1, 2 } },
|
||||
{ D3DSIO_SGE, { "sge", 1, 2 } },
|
||||
{ D3DSIO_EXP, { "exp", 1, 1 } },
|
||||
{ D3DSIO_LOG, { "log", 1, 1 } },
|
||||
{ D3DSIO_LIT, { "lit", 1, 1 } },
|
||||
{ D3DSIO_DST, { "dst", 1, 2 } },
|
||||
{ D3DSIO_LRP, { "lrp", 1, 3 } },
|
||||
{ D3DSIO_FRC, { "frc", 1, 1 } },
|
||||
{ D3DSIO_M4x4, { "m4x4", 1, 2 } },
|
||||
{ D3DSIO_M4x3, { "m4x3", 1, 2 } },
|
||||
{ D3DSIO_M3x4, { "m3x4", 1, 2 } },
|
||||
{ D3DSIO_M3x3, { "m3x3", 1, 2 } },
|
||||
{ D3DSIO_M3x2, { "m3x2", 1, 2 } },
|
||||
{ D3DSIO_CALL, { "call", 0, 1 } },
|
||||
{ D3DSIO_CALLNZ, { "callnz", 0, 2 } },
|
||||
{ D3DSIO_LOOP, { "loop", 0, 1, 0, BEGIN_BLOCK } },
|
||||
{ D3DSIO_RET, { "ret" } },
|
||||
{ D3DSIO_ENDLOOP, { "endloop", 0, 0, 0, END_BLOCK } },
|
||||
{ D3DSIO_LABEL, { "label", 0, 1 } },
|
||||
{ D3DSIO_DCL, { "dcl", 1, 0, 1 } },
|
||||
{ D3DSIO_POW, { "pow", 1, 2 } },
|
||||
{ D3DSIO_CRS, { "crs", 1, 2 } },
|
||||
{ D3DSIO_SGN, { "sgn", 1, 3 } },
|
||||
{ D3DSIO_ABS, { "abs", 1, 1 } },
|
||||
{ D3DSIO_NRM, { "nrm", 1, 1 } },
|
||||
{ D3DSIO_SINCOS, { "sincos", 1, 3 } },
|
||||
{ D3DSIO_REP, { "rep", 0, 1, 0, BEGIN_BLOCK } },
|
||||
{ D3DSIO_ENDREP, { "endrep", 0, 0, 0, END_BLOCK } },
|
||||
{ D3DSIO_IF, { "if", 0, 1, 0, BEGIN_BLOCK } },
|
||||
{ D3DSIO_IFC, { "if_", 0, 2, 0, BEGIN_BLOCK, &CMP_CONTROLS } },
|
||||
{ D3DSIO_ELSE, { "else", 0, 0, 0, BEGIN_BLOCK | END_BLOCK } },
|
||||
{ D3DSIO_ENDIF, { "endif", 0, 0, 0, END_BLOCK } },
|
||||
{ D3DSIO_BREAK, { "break" } },
|
||||
{ D3DSIO_BREAKC, { "break_", 0, 2, 0, 0, &CMP_CONTROLS } },
|
||||
{ D3DSIO_MOVA, { "mova", 1, 1 } },
|
||||
{ D3DSIO_DEFB, { "defb", 1, 0, 1 } },
|
||||
{ D3DSIO_DEFI, { "defi", 1, 0, 4 } },
|
||||
{ D3DSIO_TEXKILL, { "texkill", 1 } },
|
||||
{ D3DSIO_TEX, { "texld", 1, 2, 0, 0, &TEXLD_CONTROLS } },
|
||||
{ D3DSIO_TEXBEM, { "texbem", 1, 1 } },
|
||||
{ D3DSIO_TEXBEML, { "texbeml", 1, 1 } },
|
||||
{ D3DSIO_TEXREG2AR, { "texreg2ar", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x2PAD, { "texm3x2pad", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x2TEX, { "texm3x2tex", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x3PAD, { "texm3x3pad", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x3TEX, { "texm3x3tex", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x3SPEC, { "texm3x3spec", 1, 2 } },
|
||||
{ D3DSIO_TEXM3x3VSPEC, { "texm3x3vspec", 1, 1 } },
|
||||
{ D3DSIO_EXPP, { "expp", 1, 1 } },
|
||||
{ D3DSIO_LOGP, { "logp", 1, 1 } },
|
||||
{ D3DSIO_CND, { "cnd", 1, 3 } },
|
||||
{ D3DSIO_DEF, { "def", 1, 0, 4 } },
|
||||
{ D3DSIO_TEXREG2RGB, { "texreg2rgb", 1, 1 } },
|
||||
{ D3DSIO_TEXDP3TEX, { "texdp3tex", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x2DEPTH, { "texm3x2depth", 1, 1 } },
|
||||
{ D3DSIO_TEXDP3, { "texdp3", 1, 1 } },
|
||||
{ D3DSIO_TEXM3x3, { "texm3x3", 1, 1 } },
|
||||
{ D3DSIO_TEXDEPTH, { "texdepth", 1 } },
|
||||
{ D3DSIO_CMP, { "cmp", 1, 3 } },
|
||||
{ D3DSIO_BEM, { "bem", 1, 2 } },
|
||||
{ D3DSIO_DP2ADD, { "dp2add", 1, 3 } },
|
||||
{ D3DSIO_DSX, { "dsx", 1, 1 } },
|
||||
{ D3DSIO_DSY, { "dsy", 1, 1 } },
|
||||
{ D3DSIO_TEXLDD, { "texldd", 1, 2 } },
|
||||
{ D3DSIO_SETP, { "setp_", 1, 2, 0, 0, &CMP_CONTROLS } },
|
||||
{ D3DSIO_TEXLDL, { "texldl", 1, 2 } },
|
||||
{ D3DSIO_BREAKP, { "break pred", 0, 1 } },
|
||||
{ D3DSIO_PHASE, { "phase" } },
|
||||
{ D3DSIO_COMMENT, { "// " } },
|
||||
{ D3DSIO_END, { "end" } }
|
||||
};
|
||||
|
||||
std::map<D3DSHADER_PARAM_REGISTER_TYPE, const char*> g_registerMap = {
|
||||
{ D3DSPR_TEMP, "r" },
|
||||
{ D3DSPR_INPUT, "v" },
|
||||
{ D3DSPR_CONST, "c" },
|
||||
{ D3DSPR_ATTROUT, "oD"},
|
||||
{ D3DSPR_TEXCRDOUT, "oT" },
|
||||
{ D3DSPR_CONSTINT, "i" },
|
||||
{ D3DSPR_COLOROUT, "oD" },
|
||||
{ D3DSPR_DEPTHOUT, "oDepth" },
|
||||
{ D3DSPR_SAMPLER, "s" },
|
||||
{ D3DSPR_CONSTBOOL, "b" },
|
||||
{ D3DSPR_LABEL, "l" },
|
||||
{ D3DSPR_PREDICATE, "p" }
|
||||
};
|
||||
|
||||
std::map<UINT, const char*> g_sourceModifierPrefixMap = {
|
||||
{ D3DSPSM_NEG, "-" },
|
||||
{ D3DSPSM_BIASNEG, "-" },
|
||||
{ D3DSPSM_SIGNNEG, "-" },
|
||||
{ D3DSPSM_COMP, "1-" },
|
||||
{ D3DSPSM_X2NEG, "-" },
|
||||
{ D3DSPSM_ABSNEG, "-" },
|
||||
{ D3DSPSM_NOT, "!" }
|
||||
};
|
||||
|
||||
std::map<UINT, const char*> g_sourceModifierSuffixMap = {
|
||||
{ D3DSPSM_BIAS, "bias" },
|
||||
{ D3DSPSM_SIGN, "bx2" },
|
||||
{ D3DSPSM_X2, "x2" },
|
||||
{ D3DSPSM_DZ, "dz" },
|
||||
{ D3DSPSM_DW, "dw" },
|
||||
{ D3DSPSM_ABS, "abs" }
|
||||
};
|
||||
|
||||
std::map<UINT, const char*> g_textureTypeMap = {
|
||||
{ D3DSTT_UNKNOWN, nullptr },
|
||||
{ D3DSTT_2D, "2d" },
|
||||
{ D3DSTT_CUBE, "cube" },
|
||||
{ D3DSTT_VOLUME, "volume" }
|
||||
};
|
||||
|
||||
std::map<D3DDECLUSAGE, const char*> g_usageMap = {
|
||||
{ D3DDECLUSAGE_POSITION, "position" },
|
||||
{ D3DDECLUSAGE_BLENDWEIGHT, "blendweight" },
|
||||
{ D3DDECLUSAGE_BLENDINDICES, "blendindices" },
|
||||
{ D3DDECLUSAGE_NORMAL, "normal" },
|
||||
{ D3DDECLUSAGE_PSIZE, "psize" },
|
||||
{ D3DDECLUSAGE_TEXCOORD, "texcoord" },
|
||||
{ D3DDECLUSAGE_TANGENT, "tangent" },
|
||||
{ D3DDECLUSAGE_BINORMAL, "binormal" },
|
||||
{ D3DDECLUSAGE_TESSFACTOR, "tessfactor" },
|
||||
{ D3DDECLUSAGE_POSITIONT, "positiont" },
|
||||
{ D3DDECLUSAGE_COLOR, "color" },
|
||||
{ D3DDECLUSAGE_FOG, "fog" },
|
||||
{ D3DDECLUSAGE_DEPTH, "depth" },
|
||||
{ D3DDECLUSAGE_SAMPLE, "sample" }
|
||||
};
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
ShaderAssembler::ShaderAssembler(const UINT* code, DWORD size)
|
||||
: m_tokens(code, code + size)
|
||||
, m_pos(0)
|
||||
{
|
||||
}
|
||||
|
||||
std::string ShaderAssembler::disassemble()
|
||||
{
|
||||
auto origPos = m_pos;
|
||||
m_pos = 0;
|
||||
|
||||
std::ostringstream os;
|
||||
os << "Disassembled shader code:" << std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
disassembleVersion(os);
|
||||
UINT indent = 0;
|
||||
while (0 != getRemainingTokenCount())
|
||||
{
|
||||
os << std::endl;
|
||||
if (D3DSIO_END == disassembleInstruction(os, indent))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
os << e.what();
|
||||
}
|
||||
|
||||
m_pos = origPos;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleComment(std::ostream& os, UINT tokenCount)
|
||||
{
|
||||
auto begin = reinterpret_cast<const char*>(readTokens(tokenCount));
|
||||
auto end = begin + tokenCount * 4;
|
||||
end = std::find_if(begin, end, [](char c) { return !std::isprint(c); });
|
||||
os.write(begin, end - begin);
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleConstToken(std::ostream& os, UINT opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case D3DSIO_DEFB:
|
||||
case D3DSIO_DEFI:
|
||||
os << readToken<INT>();
|
||||
break;
|
||||
|
||||
default:
|
||||
os << readToken<FLOAT>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleDclPs(std::ostream& os)
|
||||
{
|
||||
auto token = readToken();
|
||||
auto type = token & D3DSP_TEXTURETYPE_MASK;
|
||||
auto it = g_textureTypeMap.find(type);
|
||||
if (it == g_textureTypeMap.end())
|
||||
{
|
||||
throw std::runtime_error("Unknown dcl texture type: " + std::to_string(type >> D3DSP_TEXTURETYPE_SHIFT));
|
||||
}
|
||||
if (it->second)
|
||||
{
|
||||
os << '_' << it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleDclVs(std::ostream& os)
|
||||
{
|
||||
auto token = readToken();
|
||||
auto usage = static_cast<D3DDECLUSAGE>(token & D3DSP_DCL_USAGE_MASK);
|
||||
auto it = g_usageMap.find(usage);
|
||||
if (it == g_usageMap.end())
|
||||
{
|
||||
throw std::runtime_error("Unknown dcl usage: " + std::to_string(usage));
|
||||
}
|
||||
os << '_' << it->second;
|
||||
|
||||
auto usageIndex = (token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
|
||||
if (0 != usageIndex)
|
||||
{
|
||||
os << usageIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleDestinationParameter(std::ostream& os)
|
||||
{
|
||||
auto token = readToken();
|
||||
auto dstMod = token & D3DSP_DSTMOD_MASK;
|
||||
if (dstMod & D3DSPDM_SATURATE)
|
||||
{
|
||||
os << "_sat";
|
||||
}
|
||||
if (dstMod & D3DSPDM_PARTIALPRECISION)
|
||||
{
|
||||
os << "_pp";
|
||||
}
|
||||
if (dstMod & D3DSPDM_MSAMPCENTROID)
|
||||
{
|
||||
os << "_centroid";
|
||||
}
|
||||
|
||||
os << ' ';
|
||||
disassembleRegister(os, token);
|
||||
|
||||
auto writeMask = token & D3DSP_WRITEMASK_ALL;
|
||||
if (D3DSP_WRITEMASK_ALL != writeMask)
|
||||
{
|
||||
os << '.';
|
||||
if (writeMask & D3DSP_WRITEMASK_0)
|
||||
{
|
||||
os << 'x';
|
||||
}
|
||||
if (writeMask & D3DSP_WRITEMASK_1)
|
||||
{
|
||||
os << 'y';
|
||||
}
|
||||
if (writeMask & D3DSP_WRITEMASK_2)
|
||||
{
|
||||
os << 'z';
|
||||
}
|
||||
if (writeMask & D3DSP_WRITEMASK_3)
|
||||
{
|
||||
os << 'w';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT ShaderAssembler::disassembleInstruction(std::ostream& os, UINT& indent)
|
||||
{
|
||||
auto token = readToken<InstructionToken>();
|
||||
auto it = g_instructionMap.find(token.opcode);
|
||||
if (it == g_instructionMap.end())
|
||||
{
|
||||
throw std::runtime_error("Unknown opcode: " + std::to_string(token.opcode));
|
||||
}
|
||||
|
||||
if ((it->second.indent & END_BLOCK) && indent > 0)
|
||||
{
|
||||
--indent;
|
||||
}
|
||||
|
||||
os << std::string(2 * indent, ' ') << it->second.name;
|
||||
|
||||
if (it->second.indent & BEGIN_BLOCK)
|
||||
{
|
||||
++indent;
|
||||
}
|
||||
|
||||
if (D3DSIO_COMMENT == token.opcode)
|
||||
{
|
||||
disassembleComment(os, reinterpret_cast<const CommentToken*>(&token)->tokenCount);
|
||||
return token.opcode;
|
||||
}
|
||||
|
||||
if (0 != token.control || it->second.controls)
|
||||
{
|
||||
auto control = (it->second.controls && token.control < it->second.controls->size())
|
||||
? it->second.controls->at(token.control)
|
||||
: nullptr;
|
||||
if (!control)
|
||||
{
|
||||
throw std::runtime_error("Unknown control: " + std::to_string(token.control) +
|
||||
", opcode: " + std::to_string(token.opcode));
|
||||
}
|
||||
os << control;
|
||||
}
|
||||
|
||||
auto inst = it->second;
|
||||
auto extraCount = it->second.extraCount;
|
||||
auto tokenCount = inst.dstCount + inst.srcCount + extraCount;
|
||||
if (token.tokenCount != tokenCount)
|
||||
{
|
||||
throw std::runtime_error("Instruction length mismatch: expected " + std::to_string(token.tokenCount) +
|
||||
", got " + std::to_string(tokenCount) + ", opcode: " + std::to_string(token.opcode));
|
||||
}
|
||||
|
||||
if (D3DSIO_DCL == token.opcode)
|
||||
{
|
||||
if (Pixel == getShaderType())
|
||||
{
|
||||
disassembleDclPs(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
disassembleDclVs(os);
|
||||
}
|
||||
--extraCount;
|
||||
}
|
||||
|
||||
const char* separator = " ";
|
||||
if (it->second.dstCount)
|
||||
{
|
||||
disassembleDestinationParameter(os);
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < it->second.srcCount; ++i)
|
||||
{
|
||||
os << separator;
|
||||
disassembleSourceParameter(os);
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < extraCount; ++i)
|
||||
{
|
||||
os << separator;
|
||||
disassembleConstToken(os, token.opcode);
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
return token.opcode;
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleRegister(std::ostream& os, UINT token)
|
||||
{
|
||||
auto registerType = static_cast<D3DSHADER_PARAM_REGISTER_TYPE>(
|
||||
((token & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) |
|
||||
((token & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2));
|
||||
auto registerNumber = token & D3DSP_REGNUM_MASK;
|
||||
|
||||
auto it = g_registerMap.find(registerType);
|
||||
if (it != g_registerMap.end())
|
||||
{
|
||||
os << it->second << registerNumber;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (registerType)
|
||||
{
|
||||
case D3DSPR_ADDR:
|
||||
os << (Pixel == getShaderType() ? 't' : 'a') << registerNumber;
|
||||
break;
|
||||
|
||||
case D3DSPR_RASTOUT:
|
||||
switch (registerNumber)
|
||||
{
|
||||
case D3DSRO_POSITION:
|
||||
os << "oPos";
|
||||
break;
|
||||
case D3DSRO_FOG:
|
||||
os << "oFog";
|
||||
break;
|
||||
case D3DSRO_POINT_SIZE:
|
||||
os << "oPts";
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown rasterizer output register number: " + std::to_string(registerNumber));
|
||||
}
|
||||
break;
|
||||
|
||||
case D3DSPR_CONST2:
|
||||
case D3DSPR_CONST3:
|
||||
case D3DSPR_CONST4:
|
||||
os << 'c' << (registerType - D3DSPR_CONST2 + 1) * 2048 + registerNumber;
|
||||
break;
|
||||
|
||||
default:
|
||||
os << "reg" << registerType << '/' << registerNumber;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleSourceParameter(std::ostream& os)
|
||||
{
|
||||
auto token = readToken();
|
||||
auto modifier = token & D3DSP_SRCMOD_MASK;
|
||||
auto it = g_sourceModifierPrefixMap.find(modifier);
|
||||
if (it != g_sourceModifierPrefixMap.end())
|
||||
{
|
||||
os << it->second;
|
||||
}
|
||||
|
||||
disassembleRegister(os, token);
|
||||
|
||||
it = g_sourceModifierSuffixMap.find(modifier);
|
||||
if (it != g_sourceModifierSuffixMap.end())
|
||||
{
|
||||
os << '_' << it->second;
|
||||
}
|
||||
|
||||
disassembleSourceSwizzle(os, token);
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleSourceSwizzle(std::ostream& os, UINT token)
|
||||
{
|
||||
const char component[] = { 'x', 'y', 'z', 'w' };
|
||||
UINT swizzle = token & D3DVS_SWIZZLE_MASK;
|
||||
|
||||
switch (swizzle)
|
||||
{
|
||||
case D3DSP_NOSWIZZLE:
|
||||
break;
|
||||
|
||||
case D3DSP_REPLICATERED:
|
||||
case D3DSP_REPLICATEGREEN:
|
||||
case D3DSP_REPLICATEBLUE:
|
||||
case D3DSP_REPLICATEALPHA:
|
||||
os << '.' << component[(swizzle >> D3DVS_SWIZZLE_SHIFT) & 0x3];
|
||||
break;
|
||||
|
||||
default:
|
||||
os << '.';
|
||||
swizzle >>= D3DVS_SWIZZLE_SHIFT;
|
||||
for (UINT i = 0; i < 4; ++i)
|
||||
{
|
||||
os << component[swizzle & 0x3];
|
||||
swizzle >>= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderAssembler::disassembleVersion(std::ostream& os)
|
||||
{
|
||||
auto version = readToken<VersionToken>();
|
||||
os << ((Pixel == version.type) ? "ps" : "vs")
|
||||
<< '_' << static_cast<UINT>(version.major)
|
||||
<< '_' << static_cast<UINT>(version.minor);
|
||||
if (2 != version.major || 0 != version.minor)
|
||||
{
|
||||
throw std::runtime_error("Unsupported shader version");
|
||||
}
|
||||
}
|
||||
|
||||
UINT ShaderAssembler::getRemainingTokenCount() const
|
||||
{
|
||||
return m_tokens.size() - m_pos;
|
||||
}
|
||||
|
||||
ShaderAssembler::ShaderType ShaderAssembler::getShaderType() const
|
||||
{
|
||||
return static_cast<ShaderType>(m_tokens.front() >> 16);
|
||||
}
|
||||
|
||||
UINT ShaderAssembler::readToken()
|
||||
{
|
||||
return *readTokens(1);
|
||||
}
|
||||
|
||||
template <typename Token>
|
||||
Token ShaderAssembler::readToken()
|
||||
{
|
||||
static_assert(4 == sizeof(Token));
|
||||
return *reinterpret_cast<const Token*>(readTokens(1));
|
||||
}
|
||||
|
||||
const UINT* ShaderAssembler::readTokens(UINT count)
|
||||
{
|
||||
if (count > getRemainingTokenCount())
|
||||
{
|
||||
throw std::runtime_error("Unexpected end of code");
|
||||
}
|
||||
auto tokens = m_tokens.data() + m_pos;
|
||||
m_pos += count;
|
||||
return tokens;
|
||||
}
|
||||
}
|
46
DDrawCompat/D3dDdi/ShaderAssembler.h
Normal file
46
DDrawCompat/D3dDdi/ShaderAssembler.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class ShaderAssembler
|
||||
{
|
||||
public:
|
||||
ShaderAssembler(const UINT* code, DWORD size);
|
||||
|
||||
std::string disassemble();
|
||||
|
||||
private:
|
||||
enum ShaderType
|
||||
{
|
||||
Vertex = 0xFFFE,
|
||||
Pixel = 0xFFFF
|
||||
};
|
||||
|
||||
void disassembleComment(std::ostream& os, UINT tokenCount);
|
||||
void disassembleConstToken(std::ostream& os, UINT opcode);
|
||||
void disassembleDclPs(std::ostream& os);
|
||||
void disassembleDclVs(std::ostream& os);
|
||||
void disassembleDestinationParameter(std::ostream& os);
|
||||
UINT disassembleInstruction(std::ostream& os, UINT& indent);
|
||||
void disassembleRegister(std::ostream& os, UINT token);
|
||||
void disassembleSourceParameter(std::ostream& os);
|
||||
void disassembleSourceSwizzle(std::ostream& os, UINT token);
|
||||
void disassembleVersion(std::ostream& os);
|
||||
UINT getRemainingTokenCount() const;
|
||||
ShaderType getShaderType() const;
|
||||
UINT readToken();
|
||||
const UINT* readTokens(UINT count);
|
||||
|
||||
template <typename Token>
|
||||
Token readToken();
|
||||
|
||||
std::vector<UINT> m_tokens;
|
||||
UINT m_pos;
|
||||
};
|
||||
}
|
@ -221,6 +221,7 @@
|
||||
<ClInclude Include="D3dDdi\Resource.h" />
|
||||
<ClInclude Include="D3dDdi\ResourceDeleter.h" />
|
||||
<ClInclude Include="D3dDdi\ScopedCriticalSection.h" />
|
||||
<ClInclude Include="D3dDdi\ShaderAssembler.h" />
|
||||
<ClInclude Include="D3dDdi\ShaderBlitter.h" />
|
||||
<ClInclude Include="D3dDdi\SurfaceRepository.h" />
|
||||
<ClInclude Include="D3dDdi\Visitors\AdapterCallbacksVisitor.h" />
|
||||
@ -369,6 +370,7 @@
|
||||
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp" />
|
||||
<ClCompile Include="D3dDdi\Resource.cpp" />
|
||||
<ClCompile Include="D3dDdi\ScopedCriticalSection.cpp" />
|
||||
<ClCompile Include="D3dDdi\ShaderAssembler.cpp" />
|
||||
<ClCompile Include="D3dDdi\ShaderBlitter.cpp" />
|
||||
<ClCompile Include="D3dDdi\SurfaceRepository.cpp" />
|
||||
<ClCompile Include="DDraw\Blitter.cpp" />
|
||||
|
@ -660,6 +660,9 @@
|
||||
<ClInclude Include="Config\Settings\DesktopResolution.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\ShaderAssembler.h">
|
||||
<Filter>Header Files\D3dDdi</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -1043,6 +1046,9 @@
|
||||
<ClCompile Include="Config\Settings\DesktopResolution.cpp">
|
||||
<Filter>Source Files\Config\Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3dDdi\ShaderAssembler.cpp">
|
||||
<Filter>Source Files\D3dDdi</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc">
|
||||
|
Loading…
x
Reference in New Issue
Block a user