mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-21 22:54:16 +01:00
[dxbc] Implemented basic control flow instuctions
This commit is contained in:
parent
858913ec0c
commit
1e08c0744f
@ -48,84 +48,37 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) {
|
||||||
switch (ins.op) {
|
switch (ins.opClass) {
|
||||||
case DxbcOpcode::DclGlobalFlags:
|
case DxbcInstClass::Declaration:
|
||||||
return this->emitDclGlobalFlags(ins);
|
return this->emitDcl(ins);
|
||||||
|
|
||||||
case DxbcOpcode::DclTemps:
|
case DxbcInstClass::ControlFlow:
|
||||||
return this->emitDclTemps(ins);
|
return this->emitControlFlow(ins);
|
||||||
|
|
||||||
case DxbcOpcode::DclInput:
|
case DxbcInstClass::TextureSample:
|
||||||
case DxbcOpcode::DclInputSgv:
|
|
||||||
case DxbcOpcode::DclInputSiv:
|
|
||||||
case DxbcOpcode::DclInputPs:
|
|
||||||
case DxbcOpcode::DclInputPsSgv:
|
|
||||||
case DxbcOpcode::DclInputPsSiv:
|
|
||||||
case DxbcOpcode::DclOutput:
|
|
||||||
case DxbcOpcode::DclOutputSgv:
|
|
||||||
case DxbcOpcode::DclOutputSiv:
|
|
||||||
return this->emitDclInterfaceReg(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::DclConstantBuffer:
|
|
||||||
return this->emitDclConstantBuffer(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::DclSampler:
|
|
||||||
return this->emitDclSampler(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::DclResource:
|
|
||||||
return this->emitDclResource(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::Add:
|
|
||||||
case DxbcOpcode::Div:
|
|
||||||
case DxbcOpcode::Exp:
|
|
||||||
case DxbcOpcode::Log:
|
|
||||||
case DxbcOpcode::Mad:
|
|
||||||
case DxbcOpcode::Max:
|
|
||||||
case DxbcOpcode::Min:
|
|
||||||
case DxbcOpcode::Mul:
|
|
||||||
case DxbcOpcode::Mov:
|
|
||||||
case DxbcOpcode::Rsq:
|
|
||||||
case DxbcOpcode::Sqrt:
|
|
||||||
case DxbcOpcode::IAdd:
|
|
||||||
case DxbcOpcode::IMad:
|
|
||||||
case DxbcOpcode::IMax:
|
|
||||||
case DxbcOpcode::IMin:
|
|
||||||
case DxbcOpcode::INeg:
|
|
||||||
return this->emitVectorAlu(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::Movc:
|
|
||||||
return this->emitVectorCmov(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::Eq:
|
|
||||||
case DxbcOpcode::Ge:
|
|
||||||
case DxbcOpcode::Lt:
|
|
||||||
case DxbcOpcode::Ne:
|
|
||||||
case DxbcOpcode::IEq:
|
|
||||||
case DxbcOpcode::IGe:
|
|
||||||
case DxbcOpcode::ILt:
|
|
||||||
case DxbcOpcode::INe:
|
|
||||||
return this->emitVectorCmp(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::Dp2:
|
|
||||||
case DxbcOpcode::Dp3:
|
|
||||||
case DxbcOpcode::Dp4:
|
|
||||||
return this->emitVectorDot(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::IMul:
|
|
||||||
return this->emitVectorImul(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::SinCos:
|
|
||||||
return this->emitVectorSinCos(ins);
|
|
||||||
|
|
||||||
case DxbcOpcode::Sample:
|
|
||||||
return this->emitSample(ins);
|
return this->emitSample(ins);
|
||||||
|
|
||||||
case DxbcOpcode::Ret:
|
case DxbcInstClass::VectorAlu:
|
||||||
return this->emitRet(ins);
|
return this->emitVectorAlu(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::VectorCmov:
|
||||||
|
return this->emitVectorCmov(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::VectorCmp:
|
||||||
|
return this->emitVectorCmp(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::VectorDot:
|
||||||
|
return this->emitVectorDot(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::VectorImul:
|
||||||
|
return this->emitVectorImul(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::VectorSinCos:
|
||||||
|
return this->emitVectorSinCos(ins);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::warn(
|
Logger::warn(
|
||||||
str::format("DxbcCompiler: Unhandled opcode: ",
|
str::format("DxbcCompiler: Unhandled opcode class: ",
|
||||||
ins.op));
|
ins.op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,6 +124,42 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitDcl(const DxbcShaderInstruction& ins) {
|
||||||
|
switch (ins.op) {
|
||||||
|
case DxbcOpcode::DclGlobalFlags:
|
||||||
|
return this->emitDclGlobalFlags(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclTemps:
|
||||||
|
return this->emitDclTemps(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclInput:
|
||||||
|
case DxbcOpcode::DclInputSgv:
|
||||||
|
case DxbcOpcode::DclInputSiv:
|
||||||
|
case DxbcOpcode::DclInputPs:
|
||||||
|
case DxbcOpcode::DclInputPsSgv:
|
||||||
|
case DxbcOpcode::DclInputPsSiv:
|
||||||
|
case DxbcOpcode::DclOutput:
|
||||||
|
case DxbcOpcode::DclOutputSgv:
|
||||||
|
case DxbcOpcode::DclOutputSiv:
|
||||||
|
return this->emitDclInterfaceReg(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclConstantBuffer:
|
||||||
|
return this->emitDclConstantBuffer(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclSampler:
|
||||||
|
return this->emitDclSampler(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclResource:
|
||||||
|
return this->emitDclResource(ins);
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger::warn(
|
||||||
|
str::format("DxbcCompiler: Unhandled opcode: ",
|
||||||
|
ins.op));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) {
|
||||||
// TODO implement properly
|
// TODO implement properly
|
||||||
}
|
}
|
||||||
@ -962,13 +951,191 @@ namespace dxvk {
|
|||||||
emitRegisterStore(ins.dst[0], result);
|
emitRegisterStore(ins.dst[0], result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowIf(const DxbcShaderInstruction& ins) {
|
||||||
|
// Load the first component of the condition
|
||||||
|
// operand and perform a zero test on it.
|
||||||
|
const DxbcRegisterValue condition = emitRegisterLoad(
|
||||||
|
ins.src[0], DxbcRegMask(true, false, false, false));
|
||||||
|
|
||||||
void DxbcCompiler::emitRet(const DxbcShaderInstruction& ins) {
|
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
|
||||||
|
condition, ins.controls.zeroTest);
|
||||||
|
|
||||||
|
// Declare the 'if' block. We do not know if there
|
||||||
|
// will be an 'else' block or not, so we'll assume
|
||||||
|
// that there is one and leave it empty otherwise.
|
||||||
|
DxbcCfgBlock block;
|
||||||
|
block.type = DxbcCfgBlockType::If;
|
||||||
|
block.b_if.labelIf = m_module.allocateId();
|
||||||
|
block.b_if.labelElse = m_module.allocateId();
|
||||||
|
block.b_if.labelEnd = m_module.allocateId();
|
||||||
|
block.b_if.hadElse = false;
|
||||||
|
m_controlFlowBlocks.push_back(block);
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(
|
||||||
|
block.b_if.labelEnd,
|
||||||
|
spv::SelectionControlMaskNone);
|
||||||
|
|
||||||
|
m_module.opBranchConditional(
|
||||||
|
zeroTest.id,
|
||||||
|
block.b_if.labelIf,
|
||||||
|
block.b_if.labelElse);
|
||||||
|
|
||||||
|
m_module.opLabel(block.b_if.labelIf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowElse(const DxbcShaderInstruction& ins) {
|
||||||
|
if (m_controlFlowBlocks.size() == 0
|
||||||
|
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::If
|
||||||
|
|| m_controlFlowBlocks.back().b_if.hadElse)
|
||||||
|
throw DxvkError("DxbcCompiler: 'Else' without 'If' found");
|
||||||
|
|
||||||
|
// Set the 'Else' flag so that we do
|
||||||
|
// not insert a dummy block on 'EndIf'
|
||||||
|
DxbcCfgBlock& block = m_controlFlowBlocks.back();
|
||||||
|
block.b_if.hadElse = true;
|
||||||
|
|
||||||
|
// Close the 'If' block by branching to
|
||||||
|
// the merge block we declared earlier
|
||||||
|
m_module.opBranch(block.b_if.labelEnd);
|
||||||
|
m_module.opLabel (block.b_if.labelElse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowEndIf(const DxbcShaderInstruction& ins) {
|
||||||
|
if (m_controlFlowBlocks.size() == 0
|
||||||
|
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::If)
|
||||||
|
throw DxvkError("DxbcCompiler: 'EndIf' without 'If' found");
|
||||||
|
|
||||||
|
// Remove the block from the stack, it's closed
|
||||||
|
const DxbcCfgBlock block = m_controlFlowBlocks.back();
|
||||||
|
m_controlFlowBlocks.pop_back();
|
||||||
|
|
||||||
|
// End the active 'if' or 'else' block
|
||||||
|
m_module.opBranch(block.b_if.labelEnd);
|
||||||
|
|
||||||
|
// If there was no 'else' block in this construct, we still
|
||||||
|
// have to declare it because we used it as a branch target.
|
||||||
|
if (!block.b_if.hadElse) {
|
||||||
|
m_module.opLabel (block.b_if.labelElse);
|
||||||
|
m_module.opBranch(block.b_if.labelEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare the merge block
|
||||||
|
m_module.opLabel(block.b_if.labelEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowLoop(const DxbcShaderInstruction& ins) {
|
||||||
|
// Declare the 'loop' block
|
||||||
|
DxbcCfgBlock block;
|
||||||
|
block.type = DxbcCfgBlockType::Loop;
|
||||||
|
block.b_loop.labelHeader = m_module.allocateId();
|
||||||
|
block.b_loop.labelBegin = m_module.allocateId();
|
||||||
|
block.b_loop.labelContinue = m_module.allocateId();
|
||||||
|
block.b_loop.labelBreak = m_module.allocateId();
|
||||||
|
m_controlFlowBlocks.push_back(block);
|
||||||
|
|
||||||
|
m_module.opBranch(block.b_loop.labelHeader);
|
||||||
|
m_module.opLabel (block.b_loop.labelHeader);
|
||||||
|
|
||||||
|
m_module.opLoopMerge(
|
||||||
|
block.b_loop.labelBreak,
|
||||||
|
block.b_loop.labelContinue,
|
||||||
|
spv::LoopControlMaskNone);
|
||||||
|
|
||||||
|
m_module.opBranch(block.b_loop.labelBegin);
|
||||||
|
m_module.opLabel (block.b_loop.labelBegin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowEndLoop(const DxbcShaderInstruction& ins) {
|
||||||
|
if (m_controlFlowBlocks.size() == 0
|
||||||
|
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::Loop)
|
||||||
|
throw DxvkError("DxbcCompiler: 'EndLoop' without 'Loop' found");
|
||||||
|
|
||||||
|
// Remove the block from the stack, it's closed
|
||||||
|
const DxbcCfgBlock block = m_controlFlowBlocks.back();
|
||||||
|
m_controlFlowBlocks.pop_back();
|
||||||
|
|
||||||
|
// Declare the continue block
|
||||||
|
m_module.opBranch(block.b_loop.labelContinue);
|
||||||
|
m_module.opLabel (block.b_loop.labelContinue);
|
||||||
|
|
||||||
|
// Declare the merge block
|
||||||
|
m_module.opBranch(block.b_loop.labelHeader);
|
||||||
|
m_module.opLabel (block.b_loop.labelBreak);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowBreakc(const DxbcShaderInstruction& ins) {
|
||||||
|
DxbcCfgBlock* loopBlock = cfgFindLoopBlock();
|
||||||
|
|
||||||
|
if (loopBlock == nullptr)
|
||||||
|
throw DxvkError("DxbcCompiler: 'Breakc' outside 'Loop' found");
|
||||||
|
|
||||||
|
// Perform zero test on the first component of the condition
|
||||||
|
const DxbcRegisterValue condition = emitRegisterLoad(
|
||||||
|
ins.src[0], DxbcRegMask(true, false, false, false));
|
||||||
|
|
||||||
|
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
|
||||||
|
condition, ins.controls.zeroTest);
|
||||||
|
|
||||||
|
// We basically have to wrap this into an 'if' block
|
||||||
|
const uint32_t breakBlock = m_module.allocateId();
|
||||||
|
const uint32_t mergeBlock = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(mergeBlock,
|
||||||
|
spv::SelectionControlMaskNone);
|
||||||
|
|
||||||
|
m_module.opBranchConditional(
|
||||||
|
zeroTest.id, breakBlock, mergeBlock);
|
||||||
|
|
||||||
|
m_module.opLabel(breakBlock);
|
||||||
|
m_module.opBranch(loopBlock->b_loop.labelBreak);
|
||||||
|
|
||||||
|
m_module.opLabel(mergeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowRet(const DxbcShaderInstruction& ins) {
|
||||||
// TODO implement properly
|
// TODO implement properly
|
||||||
m_module.opReturn();
|
m_module.opReturn();
|
||||||
m_module.functionEnd();
|
m_module.functionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlow(const DxbcShaderInstruction& ins) {
|
||||||
|
switch (ins.op) {
|
||||||
|
case DxbcOpcode::If:
|
||||||
|
return this->emitControlFlowIf(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Else:
|
||||||
|
return this->emitControlFlowElse(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::EndIf:
|
||||||
|
return this->emitControlFlowEndIf(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Loop:
|
||||||
|
return this->emitControlFlowLoop(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::EndLoop:
|
||||||
|
return this->emitControlFlowEndLoop(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Breakc:
|
||||||
|
return this->emitControlFlowBreakc(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Ret:
|
||||||
|
return this->emitControlFlowRet(ins);
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger::warn(str::format(
|
||||||
|
"DxbcCompiler: Unhandled instruction: ",
|
||||||
|
ins.op));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
|
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
|
||||||
DxbcRegisterValue srcValue,
|
DxbcRegisterValue srcValue,
|
||||||
@ -1131,6 +1298,23 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitRegisterZeroTest(
|
||||||
|
DxbcRegisterValue value,
|
||||||
|
DxbcZeroTest test) {
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = DxbcScalarType::Bool;
|
||||||
|
result.type.ccount = 1;
|
||||||
|
|
||||||
|
const uint32_t zeroId = m_module.constu32(0u);
|
||||||
|
const uint32_t typeId = getVectorTypeId(result.type);
|
||||||
|
|
||||||
|
result.id = test == DxbcZeroTest::TestZ
|
||||||
|
? m_module.opIEqual (typeId, value.id, zeroId)
|
||||||
|
: m_module.opINotEqual(typeId, value.id, zeroId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegisterValue DxbcCompiler::emitSrcOperandModifiers(
|
DxbcRegisterValue DxbcCompiler::emitSrcOperandModifiers(
|
||||||
DxbcRegisterValue value,
|
DxbcRegisterValue value,
|
||||||
DxbcRegModifiers modifiers) {
|
DxbcRegModifiers modifiers) {
|
||||||
@ -1433,7 +1617,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::warn(str::format(
|
Logger::warn(str::format(
|
||||||
"dxbc: Unhandled vertex sv output: ",
|
"DxbcCompiler: Unhandled vertex sv output: ",
|
||||||
svMapping.sv));
|
svMapping.sv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1538,14 +1722,26 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcCfgBlock* DxbcCompiler::cfgFindLoopBlock() {
|
||||||
|
for (auto cur = m_controlFlowBlocks.rbegin();
|
||||||
|
cur != m_controlFlowBlocks.rend(); cur++) {
|
||||||
|
if (cur->type == DxbcCfgBlockType::Loop)
|
||||||
|
return &(*cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) {
|
uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);
|
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);
|
||||||
case DxbcScalarType::Uint64: return m_module.defIntType(64, 0);
|
case DxbcScalarType::Uint64: return m_module.defIntType(64, 0);
|
||||||
case DxbcScalarType::Sint32: return m_module.defIntType(32, 1);
|
case DxbcScalarType::Sint32: return m_module.defIntType(32, 1);
|
||||||
case DxbcScalarType::Sint64: return m_module.defIntType(64, 1);
|
case DxbcScalarType::Sint64: return m_module.defIntType(64, 1);
|
||||||
case DxbcScalarType::Float32: return m_module.defFloatType(32);
|
case DxbcScalarType::Float32: return m_module.defFloatType(32);
|
||||||
case DxbcScalarType::Float64: return m_module.defFloatType(64);
|
case DxbcScalarType::Float64: return m_module.defFloatType(64);
|
||||||
|
case DxbcScalarType::Bool: return m_module.defBoolType();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw DxvkError("DxbcCompiler: Invalid scalar type");
|
throw DxvkError("DxbcCompiler: Invalid scalar type");
|
||||||
|
@ -82,6 +82,37 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class DxbcCfgBlockType : uint32_t {
|
||||||
|
If, Loop,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxbcCfgBlockIf {
|
||||||
|
uint32_t labelIf;
|
||||||
|
uint32_t labelElse;
|
||||||
|
uint32_t labelEnd;
|
||||||
|
bool hadElse;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxbcCfgBlockLoop {
|
||||||
|
uint32_t labelHeader;
|
||||||
|
uint32_t labelBegin;
|
||||||
|
uint32_t labelContinue;
|
||||||
|
uint32_t labelBreak;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxbcCfgBlock {
|
||||||
|
DxbcCfgBlockType type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
DxbcCfgBlockIf b_if;
|
||||||
|
DxbcCfgBlockLoop b_loop;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief DXBC to SPIR-V shader compiler
|
* \brief DXBC to SPIR-V shader compiler
|
||||||
*
|
*
|
||||||
@ -149,6 +180,11 @@ namespace dxvk {
|
|||||||
std::array<DxbcSampler, 16> m_samplers;
|
std::array<DxbcSampler, 16> m_samplers;
|
||||||
std::array<DxbcShaderResource, 128> m_textures;
|
std::array<DxbcShaderResource, 128> m_textures;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
// Control flow information. Stores labels for
|
||||||
|
// currently active if-else blocks and loops.
|
||||||
|
std::vector<DxbcCfgBlock> m_controlFlowBlocks;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Array of input values. Since v# registers are indexable
|
// Array of input values. Since v# registers are indexable
|
||||||
// in DXBC, we need to copy them into an array first.
|
// in DXBC, we need to copy them into an array first.
|
||||||
@ -173,14 +209,17 @@ namespace dxvk {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
// Shader interface and metadata declaration methods
|
// Shader interface and metadata declaration methods
|
||||||
|
void emitDcl(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitDclGlobalFlags(
|
void emitDclGlobalFlags(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitDclTemps(
|
void emitDclTemps(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitDclInterfaceReg(
|
void emitDclInterfaceReg(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitDclInput(
|
void emitDclInput(
|
||||||
uint32_t regIdx,
|
uint32_t regIdx,
|
||||||
@ -228,9 +267,31 @@ namespace dxvk {
|
|||||||
void emitSample(
|
void emitSample(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitRet(
|
/////////////////////////////////////
|
||||||
|
// Control flow instruction handlers
|
||||||
|
void emitControlFlowIf(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowElse(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowEndIf(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowLoop(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowEndLoop(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowBreakc(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowRet(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlow(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// Generic register manipulation methods
|
// Generic register manipulation methods
|
||||||
@ -262,6 +323,10 @@ namespace dxvk {
|
|||||||
DxbcRegisterValue emitRegisterNegate(
|
DxbcRegisterValue emitRegisterNegate(
|
||||||
DxbcRegisterValue value);
|
DxbcRegisterValue value);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitRegisterZeroTest(
|
||||||
|
DxbcRegisterValue value,
|
||||||
|
DxbcZeroTest test);
|
||||||
|
|
||||||
DxbcRegisterValue emitSrcOperandModifiers(
|
DxbcRegisterValue emitSrcOperandModifiers(
|
||||||
DxbcRegisterValue value,
|
DxbcRegisterValue value,
|
||||||
DxbcRegModifiers modifiers);
|
DxbcRegModifiers modifiers);
|
||||||
@ -333,6 +398,10 @@ namespace dxvk {
|
|||||||
uint32_t emitNewVariable(
|
uint32_t emitNewVariable(
|
||||||
const DxbcRegisterInfo& info);
|
const DxbcRegisterInfo& info);
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// Control flow block search methods
|
||||||
|
DxbcCfgBlock* cfgFindLoopBlock();
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
// Type definition methods
|
// Type definition methods
|
||||||
uint32_t getScalarTypeId(
|
uint32_t getScalarTypeId(
|
||||||
|
@ -122,6 +122,7 @@ namespace dxvk {
|
|||||||
// operands. Doing this mostly automatically means that
|
// operands. Doing this mostly automatically means that
|
||||||
// the compiler can rely on the operands being valid.
|
// the compiler can rely on the operands being valid.
|
||||||
const DxbcInstFormat format = dxbcInstructionFormat(m_instruction.op);
|
const DxbcInstFormat format = dxbcInstructionFormat(m_instruction.op);
|
||||||
|
m_instruction.opClass = format.instructionClass;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < format.operandCount; i++)
|
for (uint32_t i = 0; i < format.operandCount; i++)
|
||||||
this->decodeOperand(code, format.operands[i]);
|
this->decodeOperand(code, format.operands[i]);
|
||||||
|
@ -154,7 +154,7 @@ namespace dxvk {
|
|||||||
struct DxbcRegister {
|
struct DxbcRegister {
|
||||||
DxbcOperandType type;
|
DxbcOperandType type;
|
||||||
DxbcScalarType dataType;
|
DxbcScalarType dataType;
|
||||||
DxbcComponentCount componentCount;
|
DxbcComponentCount componentCount;
|
||||||
|
|
||||||
uint32_t idxDim;
|
uint32_t idxDim;
|
||||||
DxbcRegIndex idx[DxbcMaxRegIndexDim];
|
DxbcRegIndex idx[DxbcMaxRegIndexDim];
|
||||||
@ -225,6 +225,7 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
struct DxbcShaderInstruction {
|
struct DxbcShaderInstruction {
|
||||||
DxbcOpcode op;
|
DxbcOpcode op;
|
||||||
|
DxbcInstClass opClass;
|
||||||
DxbcOpModifiers modifiers;
|
DxbcOpModifiers modifiers;
|
||||||
DxbcShaderOpcodeControls controls;
|
DxbcShaderOpcodeControls controls;
|
||||||
DxbcShaderSampleControls sampleControls;
|
DxbcShaderSampleControls sampleControls;
|
||||||
|
@ -12,19 +12,27 @@ namespace dxvk {
|
|||||||
/* And */
|
/* And */
|
||||||
{ },
|
{ },
|
||||||
/* Break */
|
/* Break */
|
||||||
{ },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* Breakc */
|
/* Breakc */
|
||||||
{ },
|
{ 1, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* Call */
|
/* Call */
|
||||||
{ },
|
{ 1, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* Callc */
|
/* Callc */
|
||||||
{ },
|
{ 2, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* Case */
|
/* Case */
|
||||||
{ },
|
{ },
|
||||||
/* Continue */
|
/* Continue */
|
||||||
{ },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* Continuec */
|
/* Continuec */
|
||||||
{ },
|
{ 1, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* Cut */
|
/* Cut */
|
||||||
{ },
|
{ },
|
||||||
/* Default */
|
/* Default */
|
||||||
@ -60,15 +68,15 @@ namespace dxvk {
|
|||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
} },
|
} },
|
||||||
/* Else */
|
/* Else */
|
||||||
{ },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* Emit */
|
/* Emit */
|
||||||
{ },
|
{ },
|
||||||
/* EmitThenCut */
|
/* EmitThenCut */
|
||||||
{ },
|
{ },
|
||||||
/* EndIf */
|
/* EndIf */
|
||||||
{ },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* EndLoop */
|
/* EndLoop */
|
||||||
{ },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* EndSwitch */
|
/* EndSwitch */
|
||||||
{ },
|
{ },
|
||||||
/* Eq */
|
/* Eq */
|
||||||
@ -101,7 +109,9 @@ namespace dxvk {
|
|||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
|
||||||
} },
|
} },
|
||||||
/* If */
|
/* If */
|
||||||
{ },
|
{ 1, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* IEq */
|
/* IEq */
|
||||||
{ 3, DxbcInstClass::VectorCmp, {
|
{ 3, DxbcInstClass::VectorCmp, {
|
||||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Sint32 },
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Sint32 },
|
||||||
@ -175,7 +185,7 @@ namespace dxvk {
|
|||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
} },
|
} },
|
||||||
/* Loop */
|
/* Loop */
|
||||||
{ },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* Lt */
|
/* Lt */
|
||||||
{ 3, DxbcInstClass::VectorCmp, {
|
{ 3, DxbcInstClass::VectorCmp, {
|
||||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||||
@ -238,7 +248,9 @@ namespace dxvk {
|
|||||||
/* Ret */
|
/* Ret */
|
||||||
{ 0, DxbcInstClass::ControlFlow },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* Retc */
|
/* Retc */
|
||||||
{ },
|
{ 1, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* RoundNe */
|
/* RoundNe */
|
||||||
{ },
|
{ },
|
||||||
/* RoundNi */
|
/* RoundNi */
|
||||||
|
@ -29,6 +29,7 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
enum class DxbcInstClass {
|
enum class DxbcInstClass {
|
||||||
Declaration, ///< Interface or resource declaration
|
Declaration, ///< Interface or resource declaration
|
||||||
|
ControlFlow, ///< Control flow instructions
|
||||||
TextureSample, ///< Texture sampling instruction
|
TextureSample, ///< Texture sampling instruction
|
||||||
VectorAlu, ///< Component-wise vector instructions
|
VectorAlu, ///< Component-wise vector instructions
|
||||||
VectorCmov, ///< Component-wise conditional move
|
VectorCmov, ///< Component-wise conditional move
|
||||||
@ -36,7 +37,6 @@ namespace dxvk {
|
|||||||
VectorDot, ///< Dot product instruction
|
VectorDot, ///< Dot product instruction
|
||||||
VectorImul, ///< Component-wise integer multiplication
|
VectorImul, ///< Component-wise integer multiplication
|
||||||
VectorSinCos, ///< Sine and Cosine instruction
|
VectorSinCos, ///< Sine and Cosine instruction
|
||||||
ControlFlow, ///< Control flow instructions
|
|
||||||
Undefined, ///< Instruction code not defined
|
Undefined, ///< Instruction code not defined
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -470,6 +470,7 @@ namespace dxvk {
|
|||||||
Sint64 = 3,
|
Sint64 = 3,
|
||||||
Float32 = 4,
|
Float32 = 4,
|
||||||
Float64 = 5,
|
Float64 = 5,
|
||||||
|
Bool = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1267,6 +1267,44 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opLoopMerge(
|
||||||
|
uint32_t mergeBlock,
|
||||||
|
uint32_t continueTarget,
|
||||||
|
uint32_t loopControl) {
|
||||||
|
m_code.putIns (spv::OpLoopMerge, 4);
|
||||||
|
m_code.putWord(mergeBlock);
|
||||||
|
m_code.putWord(continueTarget);
|
||||||
|
m_code.putWord(loopControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opSelectionMerge(
|
||||||
|
uint32_t mergeBlock,
|
||||||
|
uint32_t selectionControl) {
|
||||||
|
m_code.putIns (spv::OpSelectionMerge, 3);
|
||||||
|
m_code.putWord(mergeBlock);
|
||||||
|
m_code.putWord(selectionControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opBranch(
|
||||||
|
uint32_t label) {
|
||||||
|
m_code.putIns (spv::OpBranch, 2);
|
||||||
|
m_code.putWord(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opBranchConditional(
|
||||||
|
uint32_t condition,
|
||||||
|
uint32_t trueLabel,
|
||||||
|
uint32_t falseLabel) {
|
||||||
|
m_code.putIns (spv::OpBranchConditional, 4);
|
||||||
|
m_code.putWord(condition);
|
||||||
|
m_code.putWord(trueLabel);
|
||||||
|
m_code.putWord(falseLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpirvModule::opReturn() {
|
void SpirvModule::opReturn() {
|
||||||
m_code.putIns (spv::OpReturn, 1);
|
m_code.putIns (spv::OpReturn, 1);
|
||||||
}
|
}
|
||||||
|
@ -434,6 +434,23 @@ namespace dxvk {
|
|||||||
uint32_t sampledImage,
|
uint32_t sampledImage,
|
||||||
uint32_t coordinates);
|
uint32_t coordinates);
|
||||||
|
|
||||||
|
void opLoopMerge(
|
||||||
|
uint32_t mergeBlock,
|
||||||
|
uint32_t continueTarget,
|
||||||
|
uint32_t loopControl);
|
||||||
|
|
||||||
|
void opSelectionMerge(
|
||||||
|
uint32_t mergeBlock,
|
||||||
|
uint32_t selectionControl);
|
||||||
|
|
||||||
|
void opBranch(
|
||||||
|
uint32_t label);
|
||||||
|
|
||||||
|
void opBranchConditional(
|
||||||
|
uint32_t condition,
|
||||||
|
uint32_t trueLabel,
|
||||||
|
uint32_t falseLabel);
|
||||||
|
|
||||||
void opReturn();
|
void opReturn();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user