diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 61fa04a35..a7c0448dd 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -2148,11 +2148,28 @@ namespace dxvk { } - void DxbcCompiler::emitControlFlowBreakc(const DxbcShaderInstruction& ins) { + void DxbcCompiler::emitControlFlowBreak(const DxbcShaderInstruction& ins) { + const bool isBreak = ins.op == DxbcOpcode::Break; + DxbcCfgBlock* loopBlock = cfgFindLoopBlock(); if (loopBlock == nullptr) - throw DxvkError("DxbcCompiler: 'Breakc' outside 'Loop' found"); + throw DxvkError("DxbcCompiler: 'Break' or 'Continue' outside 'Loop' found"); + + m_module.opBranch(isBreak + ? loopBlock->b_loop.labelBreak + : loopBlock->b_loop.labelContinue); + m_module.opLabel (m_module.allocateId()); + } + + + void DxbcCompiler::emitControlFlowBreakc(const DxbcShaderInstruction& ins) { + const bool isBreak = ins.op == DxbcOpcode::Breakc; + + DxbcCfgBlock* loopBlock = cfgFindLoopBlock(); + + if (loopBlock == nullptr) + throw DxvkError("DxbcCompiler: 'Breakc' or 'Continuec' outside 'Loop' found"); // Perform zero test on the first component of the condition const DxbcRegisterValue condition = emitRegisterLoad( @@ -2172,7 +2189,9 @@ namespace dxvk { zeroTest.id, breakBlock, mergeBlock); m_module.opLabel(breakBlock); - m_module.opBranch(loopBlock->b_loop.labelBreak); + m_module.opBranch(isBreak + ? loopBlock->b_loop.labelBreak + : loopBlock->b_loop.labelContinue); m_module.opLabel(mergeBlock); } @@ -2229,7 +2248,12 @@ namespace dxvk { case DxbcOpcode::EndLoop: return this->emitControlFlowEndLoop(ins); + case DxbcOpcode::Break: + case DxbcOpcode::Continue: + return this->emitControlFlowBreak(ins); + case DxbcOpcode::Breakc: + case DxbcOpcode::Continuec: return this->emitControlFlowBreakc(ins); case DxbcOpcode::Ret: diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index ee931d833..347c7a2be 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -427,6 +427,9 @@ namespace dxvk { void emitControlFlowEndLoop( const DxbcShaderInstruction& ins); + void emitControlFlowBreak( + const DxbcShaderInstruction& ins); + void emitControlFlowBreakc( const DxbcShaderInstruction& ins); diff --git a/src/dxbc/dxbc_decoder.cpp b/src/dxbc/dxbc_decoder.cpp index 40270c761..496faa714 100644 --- a/src/dxbc/dxbc_decoder.cpp +++ b/src/dxbc/dxbc_decoder.cpp @@ -148,6 +148,10 @@ namespace dxvk { m_instruction.sampleControls.w = aoffimmi.w; } break; + case DxbcExtOpcode::ResourceDim: + case DxbcExtOpcode::ResourceReturnType: + break; // part of resource description + default: Logger::warn(str::format( "DxbcDecodeContext: Unhandled extended opcode: ", diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index bdf0cc6d0..1b20c2253 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -30,7 +30,9 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* Case */ - { }, + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* Continue */ { 0, DxbcInstClass::ControlFlow }, /* Continuec */ @@ -90,7 +92,7 @@ namespace dxvk { /* EndLoop */ { 0, DxbcInstClass::ControlFlow }, /* EndSwitch */ - { }, + { 0, DxbcInstClass::ControlFlow }, /* Eq */ { 3, DxbcInstClass::VectorCmp, { { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, @@ -371,7 +373,9 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, } }, /* Switch */ - { }, + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* SinCos */ { 3, DxbcInstClass::VectorSinCos, { { DxbcOperandKind::DstReg, DxbcScalarType::Float32 },