1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-12 13:08:50 +01:00

[dxbc] Support switch-case fallthrough

Apparently this is a thing in Shader Model 4, although FXC cannot emit it.
This commit is contained in:
Philip Rebohle 2022-03-22 17:32:43 +01:00
parent 0d54f7161c
commit b015cf0bb2
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 36 additions and 8 deletions

View File

@ -70,6 +70,9 @@ namespace dxvk {
void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) { void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) {
m_lastOp = m_currOp;
m_currOp = ins.op;
switch (ins.opClass) { switch (ins.opClass) {
case DxbcInstClass::Declaration: case DxbcInstClass::Declaration:
return this->emitDcl(ins); return this->emitDcl(ins);
@ -3878,11 +3881,16 @@ namespace dxvk {
if (ins.src[0].type != DxbcOperandType::Imm32) if (ins.src[0].type != DxbcOperandType::Imm32)
throw DxvkError("DxbcCompiler: Invalid operand type for 'Case'"); throw DxvkError("DxbcCompiler: Invalid operand type for 'Case'");
// Use the last label allocated for 'case'. The block starting // Use the last label allocated for 'case'.
// with that label is guaranteed to be empty unless a previous
// 'case' block was not properly closed in the DXBC shader.
DxbcCfgBlockSwitch* block = &m_controlFlowBlocks.back().b_switch; DxbcCfgBlockSwitch* block = &m_controlFlowBlocks.back().b_switch;
if (caseBlockIsFallthrough()) {
block->labelCase = m_module.allocateId();
m_module.opBranch(block->labelCase);
m_module.opLabel (block->labelCase);
}
DxbcSwitchLabel label; DxbcSwitchLabel label;
label.desc.literal = ins.src[0].imm.u32_1; label.desc.literal = ins.src[0].imm.u32_1;
label.desc.labelId = block->labelCase; label.desc.labelId = block->labelCase;
@ -3896,9 +3904,17 @@ namespace dxvk {
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::Switch) || m_controlFlowBlocks.back().type != DxbcCfgBlockType::Switch)
throw DxvkError("DxbcCompiler: 'Default' without 'Switch' found"); throw DxvkError("DxbcCompiler: 'Default' without 'Switch' found");
DxbcCfgBlockSwitch* block = &m_controlFlowBlocks.back().b_switch;
if (caseBlockIsFallthrough()) {
block->labelCase = m_module.allocateId();
m_module.opBranch(block->labelCase);
m_module.opLabel (block->labelCase);
}
// Set the last label allocated for 'case' as the default label. // Set the last label allocated for 'case' as the default label.
m_controlFlowBlocks.back().b_switch.labelDefault block->labelDefault = block->labelCase;
= m_controlFlowBlocks.back().b_switch.labelCase;
} }
@ -7802,6 +7818,13 @@ namespace dxvk {
return result; return result;
} }
bool DxbcCompiler::caseBlockIsFallthrough() const {
return m_lastOp != DxbcOpcode::Case
&& m_lastOp != DxbcOpcode::Break
&& m_lastOp != DxbcOpcode::Ret;
}
uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) { uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) {
if (type == DxbcScalarType::Float64) if (type == DxbcScalarType::Float64)
m_module.enableCapability(spv::CapabilityFloat64); m_module.enableCapability(spv::CapabilityFloat64);

View File

@ -543,6 +543,9 @@ namespace dxvk {
// Global state stuff // Global state stuff
bool m_precise = true; bool m_precise = true;
DxbcOpcode m_lastOp = DxbcOpcode::Nop;
DxbcOpcode m_currOp = DxbcOpcode::Nop;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// Shader interface and metadata declaration methods // Shader interface and metadata declaration methods
void emitDcl( void emitDcl(
@ -1239,6 +1242,8 @@ namespace dxvk {
const DxbcRegister& operand, const DxbcRegister& operand,
DxbcRegisterValue vectorId); DxbcRegisterValue vectorId);
bool caseBlockIsFallthrough() const;
/////////////////////////// ///////////////////////////
// Type definition methods // Type definition methods
uint32_t getScalarTypeId( uint32_t getScalarTypeId(