mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +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) {
|
||||
switch (ins.op) {
|
||||
case DxbcOpcode::DclGlobalFlags:
|
||||
return this->emitDclGlobalFlags(ins);
|
||||
switch (ins.opClass) {
|
||||
case DxbcInstClass::Declaration:
|
||||
return this->emitDcl(ins);
|
||||
|
||||
case DxbcOpcode::DclTemps:
|
||||
return this->emitDclTemps(ins);
|
||||
case DxbcInstClass::ControlFlow:
|
||||
return this->emitControlFlow(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);
|
||||
|
||||
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:
|
||||
case DxbcInstClass::TextureSample:
|
||||
return this->emitSample(ins);
|
||||
|
||||
case DxbcOpcode::Ret:
|
||||
return this->emitRet(ins);
|
||||
case DxbcInstClass::VectorAlu:
|
||||
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:
|
||||
Logger::warn(
|
||||
str::format("DxbcCompiler: Unhandled opcode: ",
|
||||
str::format("DxbcCompiler: Unhandled opcode class: ",
|
||||
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) {
|
||||
// TODO implement properly
|
||||
}
|
||||
@ -962,13 +951,191 @@ namespace dxvk {
|
||||
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
|
||||
m_module.opReturn();
|
||||
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 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 value,
|
||||
DxbcRegModifiers modifiers) {
|
||||
@ -1433,7 +1617,7 @@ namespace dxvk {
|
||||
|
||||
default:
|
||||
Logger::warn(str::format(
|
||||
"dxbc: Unhandled vertex sv output: ",
|
||||
"DxbcCompiler: Unhandled vertex sv output: ",
|
||||
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) {
|
||||
switch (type) {
|
||||
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);
|
||||
case DxbcScalarType::Uint64: return m_module.defIntType(64, 0);
|
||||
case DxbcScalarType::Sint32: return m_module.defIntType(32, 1);
|
||||
case DxbcScalarType::Sint64: return m_module.defIntType(64, 1);
|
||||
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);
|
||||
case DxbcScalarType::Uint64: return m_module.defIntType(64, 0);
|
||||
case DxbcScalarType::Sint32: return m_module.defIntType(32, 1);
|
||||
case DxbcScalarType::Sint64: return m_module.defIntType(64, 1);
|
||||
case DxbcScalarType::Float32: return m_module.defFloatType(32);
|
||||
case DxbcScalarType::Float64: return m_module.defFloatType(64);
|
||||
case DxbcScalarType::Bool: return m_module.defBoolType();
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
@ -149,6 +180,11 @@ namespace dxvk {
|
||||
std::array<DxbcSampler, 16> m_samplers;
|
||||
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
|
||||
// in DXBC, we need to copy them into an array first.
|
||||
@ -173,14 +209,17 @@ namespace dxvk {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Shader interface and metadata declaration methods
|
||||
void emitDcl(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclGlobalFlags(
|
||||
const DxbcShaderInstruction& ins);
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclTemps(
|
||||
const DxbcShaderInstruction& ins);
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclInterfaceReg(
|
||||
const DxbcShaderInstruction& ins);
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclInput(
|
||||
uint32_t regIdx,
|
||||
@ -228,9 +267,31 @@ namespace dxvk {
|
||||
void emitSample(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitRet(
|
||||
/////////////////////////////////////
|
||||
// Control flow instruction handlers
|
||||
void emitControlFlowIf(
|
||||
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
|
||||
@ -262,6 +323,10 @@ namespace dxvk {
|
||||
DxbcRegisterValue emitRegisterNegate(
|
||||
DxbcRegisterValue value);
|
||||
|
||||
DxbcRegisterValue emitRegisterZeroTest(
|
||||
DxbcRegisterValue value,
|
||||
DxbcZeroTest test);
|
||||
|
||||
DxbcRegisterValue emitSrcOperandModifiers(
|
||||
DxbcRegisterValue value,
|
||||
DxbcRegModifiers modifiers);
|
||||
@ -333,6 +398,10 @@ namespace dxvk {
|
||||
uint32_t emitNewVariable(
|
||||
const DxbcRegisterInfo& info);
|
||||
|
||||
/////////////////////////////////////
|
||||
// Control flow block search methods
|
||||
DxbcCfgBlock* cfgFindLoopBlock();
|
||||
|
||||
///////////////////////////
|
||||
// Type definition methods
|
||||
uint32_t getScalarTypeId(
|
||||
|
@ -122,6 +122,7 @@ namespace dxvk {
|
||||
// operands. Doing this mostly automatically means that
|
||||
// the compiler can rely on the operands being valid.
|
||||
const DxbcInstFormat format = dxbcInstructionFormat(m_instruction.op);
|
||||
m_instruction.opClass = format.instructionClass;
|
||||
|
||||
for (uint32_t i = 0; i < format.operandCount; i++)
|
||||
this->decodeOperand(code, format.operands[i]);
|
||||
|
@ -154,7 +154,7 @@ namespace dxvk {
|
||||
struct DxbcRegister {
|
||||
DxbcOperandType type;
|
||||
DxbcScalarType dataType;
|
||||
DxbcComponentCount componentCount;
|
||||
DxbcComponentCount componentCount;
|
||||
|
||||
uint32_t idxDim;
|
||||
DxbcRegIndex idx[DxbcMaxRegIndexDim];
|
||||
@ -225,6 +225,7 @@ namespace dxvk {
|
||||
*/
|
||||
struct DxbcShaderInstruction {
|
||||
DxbcOpcode op;
|
||||
DxbcInstClass opClass;
|
||||
DxbcOpModifiers modifiers;
|
||||
DxbcShaderOpcodeControls controls;
|
||||
DxbcShaderSampleControls sampleControls;
|
||||
|
@ -12,19 +12,27 @@ namespace dxvk {
|
||||
/* And */
|
||||
{ },
|
||||
/* Break */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* Breakc */
|
||||
{ },
|
||||
{ 1, DxbcInstClass::ControlFlow, {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* Call */
|
||||
{ },
|
||||
{ 1, DxbcInstClass::ControlFlow, {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* Callc */
|
||||
{ },
|
||||
{ 2, DxbcInstClass::ControlFlow, {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* Case */
|
||||
{ },
|
||||
/* Continue */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* Continuec */
|
||||
{ },
|
||||
{ 1, DxbcInstClass::ControlFlow, {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* Cut */
|
||||
{ },
|
||||
/* Default */
|
||||
@ -60,15 +68,15 @@ namespace dxvk {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||
} },
|
||||
/* Else */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* Emit */
|
||||
{ },
|
||||
/* EmitThenCut */
|
||||
{ },
|
||||
/* EndIf */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* EndLoop */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* EndSwitch */
|
||||
{ },
|
||||
/* Eq */
|
||||
@ -101,7 +109,9 @@ namespace dxvk {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
|
||||
} },
|
||||
/* If */
|
||||
{ },
|
||||
{ 1, DxbcInstClass::ControlFlow, {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* IEq */
|
||||
{ 3, DxbcInstClass::VectorCmp, {
|
||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Sint32 },
|
||||
@ -175,7 +185,7 @@ namespace dxvk {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||
} },
|
||||
/* Loop */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* Lt */
|
||||
{ 3, DxbcInstClass::VectorCmp, {
|
||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||
@ -238,7 +248,9 @@ namespace dxvk {
|
||||
/* Ret */
|
||||
{ 0, DxbcInstClass::ControlFlow },
|
||||
/* Retc */
|
||||
{ },
|
||||
{ 1, DxbcInstClass::ControlFlow, {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* RoundNe */
|
||||
{ },
|
||||
/* RoundNi */
|
||||
|
@ -29,6 +29,7 @@ namespace dxvk {
|
||||
*/
|
||||
enum class DxbcInstClass {
|
||||
Declaration, ///< Interface or resource declaration
|
||||
ControlFlow, ///< Control flow instructions
|
||||
TextureSample, ///< Texture sampling instruction
|
||||
VectorAlu, ///< Component-wise vector instructions
|
||||
VectorCmov, ///< Component-wise conditional move
|
||||
@ -36,7 +37,6 @@ namespace dxvk {
|
||||
VectorDot, ///< Dot product instruction
|
||||
VectorImul, ///< Component-wise integer multiplication
|
||||
VectorSinCos, ///< Sine and Cosine instruction
|
||||
ControlFlow, ///< Control flow instructions
|
||||
Undefined, ///< Instruction code not defined
|
||||
};
|
||||
|
||||
|
@ -470,6 +470,7 @@ namespace dxvk {
|
||||
Sint64 = 3,
|
||||
Float32 = 4,
|
||||
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() {
|
||||
m_code.putIns (spv::OpReturn, 1);
|
||||
}
|
||||
|
@ -434,6 +434,23 @@ namespace dxvk {
|
||||
uint32_t sampledImage,
|
||||
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();
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user