Force A0's X mask during decoding (in VshAddInstructionMAC_ARL) instead of HLSL conversion (in OutputHlsl)

Also applied Unix EOL style (again)
This commit is contained in:
PatrickvL 2019-12-12 14:36:14 +01:00 committed by patrickvl
parent 619b276d81
commit 50a51657b0
1 changed files with 85 additions and 85 deletions

View File

@ -250,7 +250,7 @@ typedef struct _VSH_SHADER_INSTRUCTION
VSH_PARAMETER A;
VSH_PARAMETER B;
VSH_PARAMETER C;
boolean a0x;
boolean a0x;
boolean Final;
}
VSH_SHADER_INSTRUCTION;
@ -382,7 +382,7 @@ static uint8_t VshGetField(uint32_t *pShaderToken,
// Final instruction
{ 3, 0, 1 } // FLD_FINAL,
};
return (uint8_t)(VshGetFromToken(pShaderToken,
FieldMapping[FieldName].SubToken,
FieldMapping[FieldName].StartBit,
@ -398,7 +398,7 @@ static inline int16_t ConvertCRegister(const int16_t CReg)
static void VshParseInstruction(uint32_t *pShaderToken,
VSH_SHADER_INSTRUCTION *pInstruction)
{
// First get the instruction(s).
// First get the instruction(s).
pInstruction->ILU = (VSH_ILU)VshGetField(pShaderToken, FLD_ILU);
pInstruction->MAC = (VSH_MAC)VshGetField(pShaderToken, FLD_MAC);
@ -471,14 +471,14 @@ static void VshParseInstruction(uint32_t *pShaderToken,
pInstruction->C.Swizzle[3] = (VSH_SWIZZLE)VshGetField(pShaderToken, FLD_C_SWZ_W);
// Get output
// Output register
pInstruction->Output.OutputType = (VSH_OUTPUT_TYPE)VshGetField(pShaderToken, FLD_OUT_ORB);
pInstruction->Output.OutputType = (VSH_OUTPUT_TYPE)VshGetField(pShaderToken, FLD_OUT_ORB);
switch(pInstruction->Output.OutputType)
{
case OUTPUT_C:
pInstruction->Output.OutputAddress = ConvertCRegister(VshGetField(pShaderToken, FLD_OUT_ADDRESS));
break;
case OUTPUT_O:
pInstruction->Output.OutputAddress = VshGetField(pShaderToken, FLD_OUT_ADDRESS) & 0xF;
pInstruction->Output.OutputAddress = VshGetField(pShaderToken, FLD_OUT_ADDRESS) & 0xF;
break;
}
pInstruction->Output.OutputMux = (VSH_OUTPUT_MUX)VshGetField(pShaderToken, FLD_OUT_MUX);
@ -499,8 +499,8 @@ static void VshParseInstruction(uint32_t *pShaderToken,
pInstruction->Output.ILURMask[3] = VshGetField(pShaderToken, FLD_OUT_ILU_MASK_W);
pInstruction->Output.ILURAddress = VshGetField(pShaderToken, FLD_OUT_R);
// Finally, get a0.x indirect constant addressing
pInstruction->a0x = VshGetField(pShaderToken, FLD_A0X);
pInstruction->Final = VshGetField(pShaderToken, FLD_FINAL);
pInstruction->a0x = VshGetField(pShaderToken, FLD_A0X);
pInstruction->Final = VshGetField(pShaderToken, FLD_FINAL);
}
static inline int VshIsMaskInUse(const boolean* pMask)
@ -510,14 +510,14 @@ static inline int VshIsMaskInUse(const boolean* pMask)
static inline boolean VshInstrWritesToMAC_R(VSH_SHADER_INSTRUCTION* pInstruction)
{
return VshIsMaskInUse(pInstruction->Output.MACRMask)
return VshIsMaskInUse(pInstruction->Output.MACRMask)
&& pInstruction->MAC != MAC_NOP;
}
static inline boolean VshInstrWritesToMAC_O(VSH_SHADER_INSTRUCTION* pInstruction)
{
return VshIsMaskInUse(pInstruction->Output.OutputMask)
&& pInstruction->Output.OutputMux == OMUX_MAC
return VshIsMaskInUse(pInstruction->Output.OutputMask)
&& pInstruction->Output.OutputMux == OMUX_MAC
&& pInstruction->MAC != MAC_NOP;
}
@ -530,14 +530,14 @@ static inline boolean VshInstrWritesToMAC_ARL(VSH_SHADER_INSTRUCTION* pInstructi
static inline boolean VshInstrWritesToILU_R(VSH_SHADER_INSTRUCTION* pInstruction)
{
return VshIsMaskInUse(pInstruction->Output.ILURMask)
return VshIsMaskInUse(pInstruction->Output.ILURMask)
&& pInstruction->ILU != ILU_NOP;
}
static inline boolean VshInstrWritesToILU_O(VSH_SHADER_INSTRUCTION* pInstruction)
{
return VshIsMaskInUse(pInstruction->Output.OutputMask)
&& pInstruction->Output.OutputMux == OMUX_ILU
return VshIsMaskInUse(pInstruction->Output.OutputMask)
&& pInstruction->Output.OutputMux == OMUX_ILU
&& pInstruction->ILU != ILU_NOP;
}
@ -556,7 +556,7 @@ static void VshAddParameters(VSH_SHADER_INSTRUCTION *pInstruction,
VSH_IMD_PARAMETER *pParameters)
{
uint8_t ParamCount = 0;
if(MAC >= MAC_MOV)
{
VshAddParameter(&pInstruction->A, pInstruction->a0x, &pParameters[ParamCount]);
@ -597,7 +597,7 @@ static boolean VshAddInstructionMAC_R(VSH_SHADER_INSTRUCTION *pInstruction,
VSH_XBOX_SHADER *pShader,
boolean IsCombined)
{
VSH_INTERMEDIATE_FORMAT *pIntermediate;
VSH_INTERMEDIATE_FORMAT *pIntermediate;
if(!VshInstrWritesToMAC_R(pInstruction)) {
return FALSE;
@ -625,7 +625,7 @@ static boolean VshAddInstructionMAC_O(VSH_SHADER_INSTRUCTION* pInstruction,
VSH_XBOX_SHADER *pShader,
boolean IsCombined)
{
VSH_INTERMEDIATE_FORMAT *pIntermediate;
VSH_INTERMEDIATE_FORMAT *pIntermediate;
if(!VshInstrWritesToMAC_O(pInstruction)) {
return FALSE;
@ -653,7 +653,7 @@ static boolean VshAddInstructionMAC_ARL(VSH_SHADER_INSTRUCTION *pInstruction,
VSH_XBOX_SHADER *pShader,
boolean IsCombined)
{
VSH_INTERMEDIATE_FORMAT *pIntermediate;
VSH_INTERMEDIATE_FORMAT *pIntermediate;
if(!VshInstrWritesToMAC_ARL(pInstruction)) {
return FALSE;
@ -669,6 +669,7 @@ static boolean VshAddInstructionMAC_ARL(VSH_SHADER_INSTRUCTION *pInstruction,
// Output param
pIntermediate->Output.Type = IMD_OUTPUT_A0X;
pIntermediate->Output.Address = pInstruction->Output.OutputAddress;
pIntermediate->Output.Mask[0] = true; // force a0.x
// Other parameters
VshAddParameters(pInstruction, ILU_NOP, pInstruction->MAC, pIntermediate->Parameters);
@ -680,7 +681,7 @@ static boolean VshAddInstructionILU_R(VSH_SHADER_INSTRUCTION *pInstruction,
VSH_XBOX_SHADER *pShader,
boolean IsCombined)
{
VSH_INTERMEDIATE_FORMAT *pIntermediate;
VSH_INTERMEDIATE_FORMAT *pIntermediate;
if(!VshInstrWritesToILU_R(pInstruction)) {
return FALSE;
@ -709,7 +710,7 @@ static boolean VshAddInstructionILU_O(VSH_SHADER_INSTRUCTION *pInstruction,
VSH_XBOX_SHADER *pShader,
boolean IsCombined)
{
VSH_INTERMEDIATE_FORMAT *pIntermediate;
VSH_INTERMEDIATE_FORMAT *pIntermediate;
if(!VshInstrWritesToILU_O(pInstruction)) {
return FALSE;
@ -760,14 +761,14 @@ static void VshConvertToIntermediate(VSH_SHADER_INSTRUCTION *pInstruction,
IsCombined = TRUE;
}
}
if (VshAddInstructionMAC_O(pInstruction, pShader, IsCombined)) {
if (VshInstrWritesToILU_R(pInstruction) ||
VshInstrWritesToILU_O(pInstruction)) {
IsCombined = TRUE;
}
}
// Special case, arl (mov a0.x, ...)
if (VshAddInstructionMAC_ARL(pInstruction, pShader, IsCombined)) {
if (VshInstrWritesToILU_R(pInstruction) ||
@ -775,13 +776,13 @@ static void VshConvertToIntermediate(VSH_SHADER_INSTRUCTION *pInstruction,
IsCombined = TRUE;
}
}
if (VshAddInstructionILU_R(pInstruction, pShader, IsCombined)) {
if (VshInstrWritesToILU_O(pInstruction)) {
IsCombined = TRUE;
}
}
(void)VshAddInstructionILU_O(pInstruction, pShader, IsCombined);
}
@ -1592,7 +1593,7 @@ public:
// Get a preprocessed copy of the original Xbox Vertex Declaration
auto pXboxVertexDeclarationCopy = RemoveXboxDeclarationRedefinition(pXboxDeclaration);
pVertexShaderInfoToSet = pCxbxVertexShaderInfo;
pVertexShaderInfoToSet = pCxbxVertexShaderInfo;
IsFixedFunction = bIsFixedFunction;
@ -1640,7 +1641,7 @@ public:
// Free the preprocessed declaration copy
free(pXboxVertexDeclarationCopy);
for (int i = 0; i < RegVIsPresentInDeclaration.size(); i++) {
for (size_t i = 0; i < RegVIsPresentInDeclaration.size(); i++) {
pCxbxVertexShaderInfo->vRegisterInDeclaration[i] = RegVIsPresentInDeclaration[i];
EmuLog(LOG_LEVEL::DEBUG, "Vertex regs used: v%d %d", i, pCxbxVertexShaderInfo->vRegisterInDeclaration[i]);
}
@ -1777,7 +1778,7 @@ void CxbxImpl_SelectVertexShaderDirect
// HLSL outputs
static void OutputHlsl(std::stringstream& hlsl, VSH_IMD_OUTPUT& dest)
static void OutputHlsl(std::stringstream& hlsl, VSH_IMD_OUTPUT& dest)
{
static const char* OReg_Name[/*VSH_OREG_NAME*/] = {
"oPos",
@ -1800,38 +1801,37 @@ static void OutputHlsl(std::stringstream& hlsl, VSH_IMD_OUTPUT& dest)
switch (dest.Type) {
case IMD_OUTPUT_C:
hlsl << "c[" << dest.Address << "]";
LOG_TEST_CASE("Vertex shader writes to constant table");
hlsl << "c[" << dest.Address << "]";
LOG_TEST_CASE("Vertex shader writes to constant table");
break;
case IMD_OUTPUT_R:
hlsl << "r" << dest.Address;
break;
case IMD_OUTPUT_O:
case IMD_OUTPUT_O:
assert(dest.Address < OREG_A0X);
hlsl << OReg_Name[dest.Address];
hlsl << OReg_Name[dest.Address];
break;
case IMD_OUTPUT_A0X:
hlsl << "a0";
dest.Mask[0] = true; // force a0.x
hlsl << "a0";
break;
default:
default:
assert(false);
break;
}
// Write the mask as a separate argument to the opcode defines
// Write the mask as a separate argument to the opcode defines
// (No space, so that "dest,mask, ..." looks close to "dest.mask, ...")
hlsl << ",";
if (dest.Mask[0]) hlsl << "x";
if (dest.Mask[1]) hlsl << "y";
if (dest.Mask[2]) hlsl << "z";
hlsl << ",";
if (dest.Mask[0]) hlsl << "x";
if (dest.Mask[1]) hlsl << "y";
if (dest.Mask[2]) hlsl << "z";
if (dest.Mask[3]) hlsl << "w";
}
static void ParameterHlsl(std::stringstream& hlsl, VSH_IMD_PARAMETER& paramMeta)
{
// Print functions
static char* RegisterName[/*VSH_PARAMETER_TYPE*/] = {
static char* RegisterName[/*VSH_PARAMETER_TYPE*/] = {
"?", // PARAM_UNKNOWN = 0,
"r", // PARAM_R, // Temporary (scRatch) registers
"v", // PARAM_V, // Vertex registers
@ -1844,19 +1844,19 @@ static void ParameterHlsl(std::stringstream& hlsl, VSH_IMD_PARAMETER& paramMeta)
if (param.Neg) {
hlsl << "-";
}
int register_number = param.Address;
if (param.ParameterType == PARAM_C) {
if (param.ParameterType == PARAM_C) {
// Map Xbox [-96, 95] to Host [0, 191]
// Account for Xbox's negative constant indexes
register_number += 96;
register_number += 96;
if (paramMeta.IndexesWithA0_X) {
// Only display the offset if it's not 0.
if (register_number != 0) {
hlsl << "c[a0.x+" << register_number << "]";
} else {
hlsl << "c[a0.x]";
}
hlsl << "c[a0.x]";
}
} else {
hlsl << "c[" << register_number << "]";
}
@ -1891,7 +1891,7 @@ static void ParameterHlsl(std::stringstream& hlsl, VSH_IMD_PARAMETER& paramMeta)
}
}
static void BuildShader(std::stringstream& hlsl, VSH_XBOX_SHADER* pShader)
static void BuildShader(std::stringstream& hlsl, VSH_XBOX_SHADER* pShader)
{
// HLSL strings for all MAC opcodes, indexed with VSH_MAC
static std::string VSH_MAC_HLSL[/*VSH_MAC*/] = {
@ -1927,33 +1927,33 @@ static void BuildShader(std::stringstream& hlsl, VSH_XBOX_SHADER* pShader)
for (int i = 0; i < pShader->IntermediateCount; i++) {
VSH_INTERMEDIATE_FORMAT& xboxInstruction = pShader->Intermediate[i];
std::string str = "";
if (xboxInstruction.InstructionType == IMD_MAC) {
if (xboxInstruction.MAC > MAC_NOP && xboxInstruction.MAC <= MAC_ARL) {
str = VSH_MAC_HLSL[xboxInstruction.MAC];
if (xboxInstruction.InstructionType == IMD_MAC) {
if (xboxInstruction.MAC > MAC_NOP && xboxInstruction.MAC <= MAC_ARL) {
str = VSH_MAC_HLSL[xboxInstruction.MAC];
}
} else if (xboxInstruction.InstructionType == IMD_ILU) {
if (xboxInstruction.ILU > ILU_NOP) {
str = VSH_ILU_HLSL[xboxInstruction.ILU];
if (xboxInstruction.ILU > ILU_NOP) {
str = VSH_ILU_HLSL[xboxInstruction.ILU];
}
}
if (!str.empty()) {
hlsl << "\n " << str << "("; // opcode
OutputHlsl(hlsl, xboxInstruction.Output);
}
if (!str.empty()) {
hlsl << "\n " << str << "("; // opcode
OutputHlsl(hlsl, xboxInstruction.Output);
for (int i = 0; i < 3; i++) {
if (xboxInstruction.Parameters[i].Active) {
hlsl << ", ";
if (xboxInstruction.Parameters[i].Active) {
hlsl << ", ";
ParameterHlsl(hlsl, xboxInstruction.Parameters[i]);
}
}
hlsl << ");";
}
hlsl << ");";
}
}
}
std::string DebugPrependLineNumbers(std::string shaderString) {
std::stringstream shader(shaderString);
auto debugShader = std::stringstream();
@ -1994,11 +1994,11 @@ extern HRESULT EmuRecompileVshFunction
*pbUseDeclarationOnly = 0;
*pXboxFunctionSize = 0;
*ppRecompiledShader = nullptr;
if (!pShader) {
EmuLog(LOG_LEVEL::WARNING, "Couldn't allocate memory for vertex shader conversion buffer");
return E_OUTOFMEMORY;
}
}
pShader->ShaderHeader = *pXboxVertexShaderHeader;
switch (pXboxVertexShaderHeader->Version) {
@ -2022,8 +2022,8 @@ extern HRESULT EmuRecompileVshFunction
static std::string hlsl_template =
#include "core\hle\D3D8\Direct3D9\Xb.hlsl" // Note : This included .hlsl defines a raw string
;
auto hlsl_stream = std::stringstream();
auto hlsl_stream = std::stringstream();
for (pToken = (DWORD*)((uint8_t*)pXboxFunction + sizeof(XTL::X_VSH_SHADER_HEADER)); !EOI; pToken += X_VSH_INSTRUCTION_SIZE) {
VSH_SHADER_INSTRUCTION Inst;
@ -2044,13 +2044,13 @@ extern HRESULT EmuRecompileVshFunction
}
BuildShader(hlsl_stream, pShader);
std::string hlsl_str = hlsl_stream.str();
std::string hlsl_str = hlsl_stream.str();
hlsl_str = std::regex_replace(hlsl_template, std::regex("// <Xbox Shader>"), hlsl_str);
DbgVshPrintf("--- HLSL conversion ---\n");
DbgVshPrintf(DebugPrependLineNumbers(hlsl_str).c_str());
DbgVshPrintf("-----------------------\n");
hRet = D3DCompile(
hlsl_str.c_str(),
hlsl_str.length(),
@ -2064,7 +2064,7 @@ extern HRESULT EmuRecompileVshFunction
ppRecompiledShader, // out
&pErrors // ppErrorMsgs out
);
if (FAILED(hRet)) {
if (FAILED(hRet)) {
EmuLog(LOG_LEVEL::WARNING, "Couldn't assemble recompiled vertex shader");
}
@ -2073,26 +2073,26 @@ extern HRESULT EmuRecompileVshFunction
if (pErrors) {
// Log HLSL compiler errors
EmuLog(hlslErrorLogLevel, "%s", (char*)(pErrors->GetBufferPointer()));
pErrors->Release();
pErrors = nullptr;
}
pErrors->Release();
pErrors = nullptr;
}
LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG)
if (g_bPrintfOn)
if (!FAILED(hRet)) {
if (g_bPrintfOn)
if (!FAILED(hRet)) {
// Log disassembly
hRet = D3DDisassemble(
(*ppRecompiledShader)->GetBufferPointer(),
(*ppRecompiledShader)->GetBufferSize(),
D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING,
NULL,
&pErrors
);
hRet = D3DDisassemble(
(*ppRecompiledShader)->GetBufferPointer(),
(*ppRecompiledShader)->GetBufferSize(),
D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING,
NULL,
&pErrors
);
if (pErrors) {
EmuLog(hlslErrorLogLevel, "%s", (char*)(pErrors->GetBufferPointer()));
pErrors->Release();
}
}
pErrors->Release();
}
}
}
free(pShader);