mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 12:34:17 +01:00
Latte: Add support for LOOP_START_NO_AL shader instruction
This instruction is used by Injustice: Gods Among Us and Project Zero Also improved robustness of rendering to be less prone to crashing when a game tries to draw with broken shaders
This commit is contained in:
parent
60adc38205
commit
fa8bab2f39
@ -340,7 +340,7 @@ uint8 LatteMRT::GetActiveColorBufferMask(const LatteDecompilerShader* pixelShade
|
|||||||
return 0;
|
return 0;
|
||||||
cemu_assert_debug(colorControlReg.get_DEGAMMA_ENABLE() == false); // not supported
|
cemu_assert_debug(colorControlReg.get_DEGAMMA_ENABLE() == false); // not supported
|
||||||
// combine color buffer mask with pixel output mask from pixel shader
|
// combine color buffer mask with pixel output mask from pixel shader
|
||||||
colorBufferMask &= pixelShader->pixelColorOutputMask;
|
colorBufferMask &= (pixelShader ? pixelShader->pixelColorOutputMask : 0);
|
||||||
// combine color buffer mask with color channel mask from mmCB_TARGET_MASK (disable render buffer if all colors are blocked)
|
// combine color buffer mask with color channel mask from mmCB_TARGET_MASK (disable render buffer if all colors are blocked)
|
||||||
uint32 channelTargetMask = lcr.CB_TARGET_MASK.get_MASK();
|
uint32 channelTargetMask = lcr.CB_TARGET_MASK.get_MASK();
|
||||||
for (uint32 i = 0; i < 8; i++)
|
for (uint32 i = 0; i < 8; i++)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#define GPU7_CF_INST_VTX (0x02) // used only in GS copy program?
|
#define GPU7_CF_INST_VTX (0x02) // used only in GS copy program?
|
||||||
#define GPU7_CF_INST_LOOP_END (0x05)
|
#define GPU7_CF_INST_LOOP_END (0x05)
|
||||||
#define GPU7_CF_INST_LOOP_START_DX10 (0x06)
|
#define GPU7_CF_INST_LOOP_START_DX10 (0x06)
|
||||||
#define GPU7_CF_INST_LOOP_START_NO_AL (0x07) // (Seen in Project Zero)
|
#define GPU7_CF_INST_LOOP_START_NO_AL (0x07) // (Seen in Project Zero, Injustice: Gods Among Us)
|
||||||
|
|
||||||
#define GPU7_CF_INST_LOOP_BREAK (0x09)
|
#define GPU7_CF_INST_LOOP_BREAK (0x09)
|
||||||
#define GPU7_CF_INST_JUMP (0x0A)
|
#define GPU7_CF_INST_JUMP (0x0A)
|
||||||
|
@ -101,7 +101,8 @@ bool LatteDecompiler_ParseCFInstruction(LatteDecompilerShaderContext* shaderCont
|
|||||||
// ignored (we use ALU/IF/ELSE/PUSH/POP clauses to determine code flow)
|
// ignored (we use ALU/IF/ELSE/PUSH/POP clauses to determine code flow)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (cf_inst23_7 == GPU7_CF_INST_LOOP_START_DX10 || cf_inst23_7 == GPU7_CF_INST_LOOP_END)
|
else if (cf_inst23_7 == GPU7_CF_INST_LOOP_START_DX10 || cf_inst23_7 == GPU7_CF_INST_LOOP_END ||
|
||||||
|
cf_inst23_7 == GPU7_CF_INST_LOOP_START_NO_AL)
|
||||||
{
|
{
|
||||||
LatteDecompilerCFInstruction& cfInstruction = instructionList.emplace_back();
|
LatteDecompilerCFInstruction& cfInstruction = instructionList.emplace_back();
|
||||||
// set type and address
|
// set type and address
|
||||||
@ -966,7 +967,8 @@ void LatteDecompiler_ParseClauses(LatteDecompilerShaderContext* decompilerContex
|
|||||||
{
|
{
|
||||||
// no sub-instructions
|
// no sub-instructions
|
||||||
}
|
}
|
||||||
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END)
|
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END ||
|
||||||
|
cfInstruction.type == GPU7_CF_INST_LOOP_START_NO_AL)
|
||||||
{
|
{
|
||||||
// no sub-instructions
|
// no sub-instructions
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,8 @@ void LatteDecompiler_analyzeSubroutine(LatteDecompilerShaderContext* shaderConte
|
|||||||
{
|
{
|
||||||
shaderContext->analyzer.modifiesPixelActiveState = true;
|
shaderContext->analyzer.modifiesPixelActiveState = true;
|
||||||
}
|
}
|
||||||
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END)
|
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END ||
|
||||||
|
cfInstruction.type == GPU7_CF_INST_LOOP_START_NO_AL)
|
||||||
{
|
{
|
||||||
shaderContext->analyzer.modifiesPixelActiveState = true;
|
shaderContext->analyzer.modifiesPixelActiveState = true;
|
||||||
}
|
}
|
||||||
@ -685,7 +686,8 @@ void LatteDecompiler_analyze(LatteDecompilerShaderContext* shaderContext, LatteD
|
|||||||
{
|
{
|
||||||
shaderContext->analyzer.modifiesPixelActiveState = true;
|
shaderContext->analyzer.modifiesPixelActiveState = true;
|
||||||
}
|
}
|
||||||
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END)
|
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END ||
|
||||||
|
cfInstruction.type == GPU7_CF_INST_LOOP_START_NO_AL)
|
||||||
{
|
{
|
||||||
shaderContext->analyzer.modifiesPixelActiveState = true;
|
shaderContext->analyzer.modifiesPixelActiveState = true;
|
||||||
shaderContext->analyzer.hasLoops = true;
|
shaderContext->analyzer.hasLoops = true;
|
||||||
@ -929,7 +931,8 @@ void LatteDecompiler_analyze(LatteDecompilerShaderContext* shaderContext, LatteD
|
|||||||
if (cfCurrentStackDepth < 0)
|
if (cfCurrentStackDepth < 0)
|
||||||
debugBreakpoint();
|
debugBreakpoint();
|
||||||
}
|
}
|
||||||
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END)
|
else if (cfInstruction.type == GPU7_CF_INST_LOOP_START_DX10 || cfInstruction.type == GPU7_CF_INST_LOOP_END ||
|
||||||
|
cfInstruction.type == GPU7_CF_INST_LOOP_START_NO_AL)
|
||||||
{
|
{
|
||||||
// no effect on stack depth
|
// no effect on stack depth
|
||||||
cfInstruction.activeStackDepth = cfCurrentStackDepth;
|
cfInstruction.activeStackDepth = cfCurrentStackDepth;
|
||||||
|
@ -3662,7 +3662,8 @@ void LatteDecompiler_emitClauseCode(LatteDecompilerShaderContext* shaderContext,
|
|||||||
{
|
{
|
||||||
src->addFmt("{} = {} == true && {} == true;" _CRLF, _getActiveMaskCVarName(shaderContext, cfInstruction->activeStackDepth + 1 - cfInstruction->popCount), _getActiveMaskVarName(shaderContext, cfInstruction->activeStackDepth - cfInstruction->popCount), _getActiveMaskCVarName(shaderContext, cfInstruction->activeStackDepth - cfInstruction->popCount));
|
src->addFmt("{} = {} == true && {} == true;" _CRLF, _getActiveMaskCVarName(shaderContext, cfInstruction->activeStackDepth + 1 - cfInstruction->popCount), _getActiveMaskVarName(shaderContext, cfInstruction->activeStackDepth - cfInstruction->popCount), _getActiveMaskCVarName(shaderContext, cfInstruction->activeStackDepth - cfInstruction->popCount));
|
||||||
}
|
}
|
||||||
else if( cfInstruction->type == GPU7_CF_INST_LOOP_START_DX10 )
|
else if( cfInstruction->type == GPU7_CF_INST_LOOP_START_DX10 ||
|
||||||
|
cfInstruction->type == GPU7_CF_INST_LOOP_START_NO_AL)
|
||||||
{
|
{
|
||||||
// start of loop
|
// start of loop
|
||||||
// if pixel is disabled, then skip loop
|
// if pixel is disabled, then skip loop
|
||||||
|
@ -1285,9 +1285,9 @@ void VulkanRenderer::draw_beginSequence()
|
|||||||
|
|
||||||
// update shader state
|
// update shader state
|
||||||
LatteSHRC_UpdateActiveShaders();
|
LatteSHRC_UpdateActiveShaders();
|
||||||
if (m_state.drawSequenceSkip)
|
if (LatteGPUState.activeShaderHasError)
|
||||||
{
|
{
|
||||||
debug_printf("Skipping drawcalls due to shader error\n");
|
cemuLog_logDebugOnce(LogType::Force, "Skipping drawcalls due to shader error");
|
||||||
m_state.drawSequenceSkip = true;
|
m_state.drawSequenceSkip = true;
|
||||||
cemu_assert_debug(false);
|
cemu_assert_debug(false);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user