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:
parent
0d54f7161c
commit
b015cf0bb2
@ -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);
|
||||||
|
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user